fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / message / fusion / mptscsih.c
index ce66f41..f0cca3e 100644 (file)
@@ -1,32 +1,11 @@
 /*
  *  linux/drivers/message/fusion/mptscsih.c
- *      High performance SCSI / Fibre Channel SCSI Host device driver.
- *      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:
- *      This driver would not exist if not for Alan Cox's development
- *      of the linux i2o driver.
- *
- *      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.
- *
- *      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!
- *
- *      (see mptbase.c)
- *
- *  Copyright (c) 1999-2004 LSI Logic Corporation
- *  Original author: Steven J. Ralston
- *  (mailto:sjralston1@netscape.net)
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
- *  $Id: mptscsih.c,v 1.104 2002/12/03 21:26:34 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -65,6 +44,7 @@
 */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
+#include "linux_compat.h"      /* linux-2.6 tweaks */
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>       /* for mdelay */
 #include <linux/interrupt.h>   /* needed for in_interrupt() proto */
 #include <linux/reboot.h>      /* notifier code */
-#include "../../scsi/scsi.h"
-#include <scsi/scsi_host.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
 
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_dbg.h>
 
 #include "mptbase.h"
 #include "mptscsih.h"
-#include "isense.h"
+#include "lsi/mpi_log_sas.h"
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #define my_NAME                "Fusion MPT SCSI Host driver"
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
-
-/* Set string for command line args from insmod */
-#ifdef MODULE
-char *mptscsih = 0;
-#endif
+MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
@@ -108,13 +90,15 @@ typedef struct _BIG_SENSE_BUF {
 #define MPT_SCANDV_SOME_ERROR          (0x00000004)
 #define MPT_SCANDV_SELECTION_TIMEOUT   (0x00000008)
 #define MPT_SCANDV_ISSUE_SENSE         (0x00000010)
+#define MPT_SCANDV_FALLBACK            (0x00000020)
 
 #define MPT_SCANDV_MAX_RETRIES         (10)
 
 #define MPT_ICFLAG_BUF_CAP     0x01    /* ReadBuffer Read Capacity format */
 #define MPT_ICFLAG_ECHO                0x02    /* ReadBuffer Echo buffer format */
-#define MPT_ICFLAG_PHYS_DISK   0x04    /* Any SCSI IO but do Phys Disk Format */
-#define MPT_ICFLAG_TAGGED_CMD  0x08    /* Do tagged IO */
+#define MPT_ICFLAG_EBOS                0x04    /* ReadBuffer Echo buffer has EBOS */
+#define MPT_ICFLAG_PHYS_DISK   0x08    /* Any SCSI IO but do Phys Disk Format */
+#define MPT_ICFLAG_TAGGED_CMD  0x10    /* Do tagged IO */
 #define MPT_ICFLAG_DID_RESET   0x20    /* Bus Reset occurred with this command */
 #define MPT_ICFLAG_RESERVED    0x40    /* Reserved has been issued */
 
@@ -132,242 +116,42 @@ typedef struct _internal_cmd {
        u8              rsvd;
 } INTERNAL_CMD;
 
-typedef struct _negoparms {
-       u8 width;
-       u8 offset;
-       u8 factor;
-       u8 flags;
-} NEGOPARMS;
-
-typedef struct _dv_parameters {
-       NEGOPARMS        max;
-       NEGOPARMS        now;
-       u8               cmd;
-       u8               id;
-       u16              pad1;
-} DVPARAMETERS;
-
-
 /*
  *  Other private/forward protos...
  */
-static int     mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
-static void    mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
-static int     mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+int            mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+static void    mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
+int            mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 
-static int     mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
+static int     mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
                                 SCSIIORequest_t *pReq, int req_idx);
-static void    mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
-static int     mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
-static void    copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
+static void    mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
+static void    mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 static int     mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
-static u32     SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
-static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
-static void    post_pendingQ_commands(MPT_SCSI_HOST *hd);
-
-static int     mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
-static int     mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
-
-static int     mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
-static int     mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
-
-static void    mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
-void           mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
-static void    mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
-static void    mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
-static void    mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
-static int     mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
+static int     mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
+static int     SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
+
+static int     mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+
+int            mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+int            mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+
+static void    mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
+static void    mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
 static int     mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
-static int     mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
-static void    mptscsih_timer_expired(unsigned long data);
-static void    mptscsih_taskmgmt_timeout(unsigned long data);
-static void    mptscsih_schedule_reset(void *hd);
+int            mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static int     mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
-static int     mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
-
-static struct mpt_work_struct   mptscsih_rstTask;
-
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-static int     mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
-static void    mptscsih_domainValidation(void *hd);
-static int     mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
-static void    mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
-static int     mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
-static void    mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
-static void    mptscsih_fillbuf(char *buffer, int size, int index, int width);
-#endif
-#ifdef MODULE
-static int     mptscsih_setup(char *str);
-#endif
-/* module entry point */
-static int  __init   mptscsih_init  (void);
-static void __exit   mptscsih_exit  (void);
+static void    mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
 
-static int  mptscsih_probe (struct pci_dev *, const struct pci_device_id *);
-static void mptscsih_remove(struct pci_dev *);
-static void mptscsih_shutdown(struct device *);
+void           mptscsih_remove(struct pci_dev *);
+void           mptscsih_shutdown(struct pci_dev *);
 #ifdef CONFIG_PM
-static int mptscsih_suspend(struct pci_dev *pdev, u32 state);
-static int mptscsih_resume(struct pci_dev *pdev);
+int            mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
+int            mptscsih_resume(struct pci_dev *pdev);
 #endif
 
-
-/*
- *     Private data...
- */
-
-static int     mpt_scsi_hosts = 0;
-
-static int     ScsiDoneCtx = -1;
-static int     ScsiTaskCtx = -1;
-static int     ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
-
 #define SNS_LEN(scp)   sizeof((scp)->sense_buffer)
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*
- * Domain Validation task structure
- */
-static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
-static int dvtaskQ_active = 0;
-static int dvtaskQ_release = 0;
-static struct mpt_work_struct  mptscsih_dvTask;
-#endif
-
-/*
- * Wait Queue setup
- */
-static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
-static int scandv_wait_done = 1;
-
-/* Driver default setup
- */
-static struct mptscsih_driver_setup
-       driver_setup = MPTSCSIH_DRIVER_SETUP;
-
-#ifdef MPTSCSIH_DBG_TIMEOUT
-static Scsi_Cmnd *foo_to[8];
-#endif
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/* see mptscsih.h */
-
-static struct scsi_host_template driver_template = {
-       .proc_name                      = "mptscsih",
-       .proc_info                      = x_scsi_proc_info,
-       .name                           = "MPT SCSI Host",
-       .info                           = x_scsi_info,
-       .queuecommand                   = x_scsi_queuecommand,
-       .slave_alloc                    = x_scsi_slave_alloc,
-       .slave_configure                = x_scsi_slave_configure,
-       .slave_destroy                  = x_scsi_slave_destroy,
-       .eh_abort_handler               = x_scsi_abort,
-       .eh_device_reset_handler        = x_scsi_dev_reset,
-       .eh_bus_reset_handler           = x_scsi_bus_reset,
-       .eh_host_reset_handler          = x_scsi_host_reset,
-       .bios_param                     = x_scsi_bios_param,
-       .can_queue                      = MPT_SCSI_CAN_QUEUE,
-       .this_id                        = -1,
-       .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
-       .max_sectors                    = MPT_SCSI_MAX_SECTORS,
-       .cmd_per_lun                    = MPT_SCSI_CMD_PER_LUN,
-       .use_clustering                 = ENABLE_CLUSTERING,
-};
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Private inline routines...
- */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* 19991030 -sralston
- *  Return absolute SCSI data direction:
- *     1 = _DATA_OUT
- *     0 = _DIR_NONE
- *    -1 = _DATA_IN
- *
- * Changed: 3-20-2002 pdelaney to use the default data
- * direction and the defines set up in the
- * 2.4 kernel series
- *     1 = _DATA_OUT   changed to SCSI_DATA_WRITE (1)
- *     0 = _DIR_NONE   changed to SCSI_DATA_NONE (3)
- *    -1 = _DATA_IN    changed to SCSI_DATA_READ (2)
- * If the direction is unknown, fall through to original code.
- *
- * Mid-layer bug fix(): sg interface generates the wrong data
- * direction in some cases. Set the direction the hard way for
- * the most common commands.
- */
-static inline int
-mptscsih_io_direction(Scsi_Cmnd *cmd)
-{
-       switch (cmd->cmnd[0]) {
-       case WRITE_6:
-       case WRITE_10:
-       case WRITE_16:
-               return SCSI_DATA_WRITE;
-               break;
-       case READ_6:
-       case READ_10:
-       case READ_16:
-               return SCSI_DATA_READ;
-               break;
-       }
-
-       if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN)
-               return cmd->sc_data_direction;
-
-       switch (cmd->cmnd[0]) {
-       /*  _DATA_OUT commands  */
-       case WRITE_6:           case WRITE_10:          case WRITE_12:
-       case WRITE_16:
-       case WRITE_LONG:        case WRITE_SAME:        case WRITE_BUFFER:
-       case WRITE_VERIFY:      case WRITE_VERIFY_12:
-       case COMPARE:           case COPY:              case COPY_VERIFY:
-       case SEARCH_EQUAL:      case SEARCH_HIGH:       case SEARCH_LOW:
-       case SEARCH_EQUAL_12:   case SEARCH_HIGH_12:    case SEARCH_LOW_12:
-       case MODE_SELECT:       case MODE_SELECT_10:    case LOG_SELECT:
-       case SEND_DIAGNOSTIC:   case CHANGE_DEFINITION: case UPDATE_BLOCK:
-       case SET_WINDOW:        case MEDIUM_SCAN:       case SEND_VOLUME_TAG:
-       case REASSIGN_BLOCKS:
-       case PERSISTENT_RESERVE_OUT:
-       case 0xea:
-       case 0xa3:
-               return SCSI_DATA_WRITE;
-
-       /*  No data transfer commands  */
-       case SEEK_6:            case SEEK_10:
-       case RESERVE:           case RELEASE:
-       case TEST_UNIT_READY:
-       case START_STOP:
-       case ALLOW_MEDIUM_REMOVAL:
-               return SCSI_DATA_NONE;
-
-       /*  Conditional data transfer commands  */
-       case FORMAT_UNIT:
-               if (cmd->cmnd[1] & 0x10)        /* FmtData (data out phase)? */
-                       return SCSI_DATA_WRITE;
-               else
-                       return SCSI_DATA_NONE;
-
-       case VERIFY:
-               if (cmd->cmnd[1] & 0x02)        /* VERIFY:BYTCHK (data out phase)? */
-                       return SCSI_DATA_WRITE;
-               else
-                       return SCSI_DATA_NONE;
-
-       case RESERVE_10:
-               if (cmd->cmnd[1] & 0x03)        /* RESERVE:{LongID|Extent} (data out phase)? */
-                       return SCSI_DATA_WRITE;
-               else
-                       return SCSI_DATA_NONE;
-
-       /*  Must be data _IN!  */
-       default:
-               return SCSI_DATA_READ;
-       }
-} /* mptscsih_io_direction() */
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_add_sge - Place a simple SGE at address pAddr.
@@ -434,44 +218,44 @@ mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     mptscsih_getFreeChainBuffes - Function to get a free chain
+ *     mptscsih_getFreeChainBuffer - Function to get a free chain
  *     from the MPT_SCSI_HOST FreeChainQ.
- *     @hd: Pointer to the MPT_SCSI_HOST instance
+ *     @ioc: Pointer to MPT_ADAPTER structure
  *     @req_idx: Index of the SCSI IO request frame. (output)
  *
  *     return SUCCESS or FAILED
  */
 static inline int
-mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
+mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
 {
        MPT_FRAME_HDR *chainBuf;
        unsigned long flags;
        int rc;
        int chain_idx;
 
-       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-       if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
-
+       dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
+                       ioc->name));
+       spin_lock_irqsave(&ioc->FreeQlock, flags);
+       if (!list_empty(&ioc->FreeChainQ)) {
                int offset;
 
-               chainBuf = hd->FreeChainQ.head;
-               Q_DEL_ITEM(&chainBuf->u.frame.linkage);
-               offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
-               chain_idx = offset / hd->ioc->req_sz;
+               chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
+                               u.frame.linkage.list);
+               list_del(&chainBuf->u.frame.linkage.list);
+               offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
+               chain_idx = offset / ioc->req_sz;
                rc = SUCCESS;
-       }
-       else {
+               dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
+                       ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
+       } else {
                rc = FAILED;
                chain_idx = MPT_HOST_NO_CHAIN;
+               dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
+                       ioc->name));
        }
-       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-
+       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
        *retIndex = chain_idx;
-
-       dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
-                       hd->ioc->name, *retIndex, chainBuf));
-
        return rc;
 } /* mptscsih_getFreeChainBuffer() */
 
@@ -479,14 +263,14 @@ mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
 /*
  *     mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
  *     SCSIIORequest_t Message Frame.
- *     @hd: Pointer to MPT_SCSI_HOST structure
- *     @SCpnt: Pointer to Scsi_Cmnd structure
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *     @SCpnt: Pointer to scsi_cmnd structure
  *     @pReq: Pointer to SCSIIORequest_t structure
  *
  *     Returns ...
  */
 static int
-mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
+mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
                SCSIIORequest_t *pReq, int req_idx)
 {
        char    *psge;
@@ -502,6 +286,7 @@ mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
        int      newIndex;
        int      ii;
        dma_addr_t v2;
+       u32     RequestNB;
 
        sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
        if (sgdir == MPI_SCSIIO_CONTROL_WRITE)  {
@@ -511,37 +296,28 @@ mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
        }
 
        psge = (char *) &pReq->SGL;
-       frm_sz = hd->ioc->req_sz;
+       frm_sz = ioc->req_sz;
 
        /* Map the data portion, if any.
         * sges_left  = 0 if no data transfer.
         */
        if ( (sges_left = SCpnt->use_sg) ) {
-               sges_left = pci_map_sg(hd->ioc->pcidev,
+               sges_left = pci_map_sg(ioc->pcidev,
                               (struct scatterlist *) SCpnt->request_buffer,
-                              SCpnt->use_sg,
-                              scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+                              SCpnt->use_sg,
+                              SCpnt->sc_data_direction);
                if (sges_left == 0)
                        return FAILED;
        } else if (SCpnt->request_bufflen) {
-               dma_addr_t       buf_dma_addr;
-               scPrivate       *my_priv;
-
-               buf_dma_addr = pci_map_single(hd->ioc->pcidev,
+               SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
                                      SCpnt->request_buffer,
                                      SCpnt->request_bufflen,
-                                     scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-
-               /* We hide it here for later unmap. */
-               my_priv = (scPrivate *) &SCpnt->SCp;
-               my_priv->p1 = (void *)(ulong) buf_dma_addr;
-
+                                     SCpnt->sc_data_direction);
                dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
-                               hd->ioc->name, SCpnt, SCpnt->request_bufflen));
-
+                               ioc->name, SCpnt, SCpnt->request_bufflen));
                mptscsih_add_sge((char *) &pReq->SGL,
                        0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
-                       buf_dma_addr);
+                       SCpnt->SCp.dma_handle);
 
                return SUCCESS;
        }
@@ -613,12 +389,16 @@ nextSGEset:
                         * Update the chain element
                         * Offset and Length fields.
                         */
-                       mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
+                       mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
                } else {
                        /* The current buffer is the original MF
                         * and there is no Chain buffer.
                         */
                        pReq->ChainOffset = 0;
+                       RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
+                       dsgprintk((MYIOC_s_INFO_FMT
+                           "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
+                       ioc->RequestNB[req_idx] = RequestNB;
                }
        } else {
                /* At least one chain buffer is needed.
@@ -633,7 +413,7 @@ nextSGEset:
                 */
 
                dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
-                               hd->ioc->name, sg_done));
+                               ioc->name, sg_done));
 
                /* Set LAST_ELEMENT flag for last non-chain element
                 * in the buffer. Since psge points at the NEXT
@@ -657,13 +437,16 @@ nextSGEset:
                         */
                        u8 nextChain = (u8) (sgeOffset >> 2);
                        sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
-                       mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
+                       mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
                } else {
                        /* The original MF buffer requires a chain buffer -
                         * set the offset.
                         * Last element in this MF is a chain element.
                         */
                        pReq->ChainOffset = (u8) (sgeOffset >> 2);
+                       RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
+                       dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
+                       ioc->RequestNB[req_idx] = RequestNB;
                }
 
                sges_left -= sg_done;
@@ -672,19 +455,23 @@ nextSGEset:
                /* NOTE: psge points to the beginning of the chain element
                 * in current buffer. Get a chain buffer.
                 */
-               if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
+               if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
+                       dfailprintk((MYIOC_s_INFO_FMT
+                           "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
+                           ioc->name, pReq->CDB[0], SCpnt));
                        return FAILED;
+               }
 
                /* Update the tracking arrays.
                 * If chainSge == NULL, update ReqToChain, else ChainToChain
                 */
                if (chainSge) {
-                       hd->ChainToChain[chain_idx] = newIndex;
+                       ioc->ChainToChain[chain_idx] = newIndex;
                } else {
-                       hd->ReqToChain[req_idx] = newIndex;
+                       ioc->ReqToChain[req_idx] = newIndex;
                }
                chain_idx = newIndex;
-               chain_dma_off = hd->ioc->req_sz * chain_idx;
+               chain_dma_off = ioc->req_sz * chain_idx;
 
                /* Populate the chainSGE for the current buffer.
                 * - Set chain buffer pointer to psge and fill
@@ -696,7 +483,7 @@ nextSGEset:
 
                /* Start the SGE for the next buffer
                 */
-               psge = (char *) (hd->ChainBuffer + chain_dma_off);
+               psge = (char *) (ioc->ChainBuffer + chain_dma_off);
                sgeOffset = 0;
                sg_done = 0;
 
@@ -712,6 +499,34 @@ nextSGEset:
        return SUCCESS;
 } /* mptscsih_AddSGE() */
 
+static void
+mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
+    U32 SlotStatus)
+{
+       MPT_FRAME_HDR *mf;
+       SEPRequest_t     *SEPMsg;
+
+       if (ioc->bus_type == FC)
+               return;
+
+       if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
+               dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
+                   ioc->name,__FUNCTION__));
+               return;
+       }
+
+       SEPMsg = (SEPRequest_t *)mf;
+       SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
+       SEPMsg->Bus = vtarget->bus_id;
+       SEPMsg->TargetID = vtarget->target_id;
+       SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
+       SEPMsg->SlotStatus = SlotStatus;
+       devtverboseprintk((MYIOC_s_WARN_FMT
+           "Sending SEP cmd=%x id=%d bus=%d\n",
+           ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
+       mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mptscsih_io_done - Main SCSI IO callback routine registered to
@@ -727,19 +542,35 @@ nextSGEset:
  *
  *     Returns 1 indicating alloc'd request frame ptr should be freed.
  */
-static int
+int
 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 {
-       Scsi_Cmnd       *sc;
+       struct scsi_cmnd        *sc;
        MPT_SCSI_HOST   *hd;
        SCSIIORequest_t *pScsiReq;
        SCSIIOReply_t   *pScsiReply;
-       u16              req_idx;
+       u16              req_idx, req_idx_MR;
+       VirtDevice       *vdev;
+       VirtTarget       *vtarget;
 
        hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
 
        req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+       req_idx_MR = (mr != NULL) ?
+           le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
+       if ((req_idx != req_idx_MR) ||
+           (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
+               printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
+                   ioc->name);
+               printk (MYIOC_s_ERR_FMT
+                   "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
+                   ioc->name, req_idx, req_idx_MR, mf, mr,
+                   hd->ScsiLookup[req_idx_MR]);
+               return 0;
+       }
+
        sc = hd->ScsiLookup[req_idx];
+       hd->ScsiLookup[req_idx] = NULL;
        if (sc == NULL) {
                MPIHeader_t *hdr = (MPIHeader_t *)mf;
 
@@ -751,38 +582,29 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
                        ioc->name);
 
-               mptscsih_freeChainBuffers(hd, req_idx);
+               mptscsih_freeChainBuffers(ioc, req_idx);
                return 1;
        }
 
-       dmfprintk((MYIOC_s_INFO_FMT
-               "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
-               ioc->name, mf, mr, sc, req_idx));
+       if ((unsigned char *)mf != sc->host_scribble) {
+               mptscsih_freeChainBuffers(ioc, req_idx);
+               return 1;
+       }
 
+       sc->host_scribble = NULL;
        sc->result = DID_OK << 16;              /* Set default reply as OK */
        pScsiReq = (SCSIIORequest_t *) mf;
        pScsiReply = (SCSIIOReply_t *) mr;
 
-#ifdef MPTSCSIH_DBG_TIMEOUT
-       if (ioc->timeout_cnt > 0) {
-               int ii, left = 0;
-
-               for (ii=0; ii < 8; ii++) {
-                       if (sc == foo_to[ii]) {
-                               printk(MYIOC_s_INFO_FMT "complete (%p, %ld)\n",
-                                       ioc->name, sc, jiffies);
-                               foo_to[ii] = NULL;
-                       }
-                       if (foo_to[ii] != NULL)
-                               left++;
-               }
-
-               if (left == 0) {
-                       ioc->timeout_maxcnt = 0;
-                       ioc->timeout_cnt = 0;
-               }
+       if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
+               dmfprintk((MYIOC_s_INFO_FMT
+                       "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
+                       ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
+       }else{
+               dmfprintk((MYIOC_s_INFO_FMT
+                       "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
+                       ioc->name, mf, mr, sc, req_idx));
        }
-#endif
 
        if (pScsiReply == NULL) {
                /* special context reply handling */
@@ -794,23 +616,41 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
                status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
                scsi_state = pScsiReply->SCSIState;
+               scsi_status = pScsiReply->SCSIStatus;
+               xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
+               sc->resid = sc->request_bufflen - xfer_cnt;
+
+               /*
+                *  if we get a data underrun indication, yet no data was
+                *  transferred and the SCSI status indicates that the
+                *  command was never started, change the data underrun
+                *  to success
+                */
+               if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
+                   (scsi_status == MPI_SCSI_STATUS_BUSY ||
+                    scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
+                    scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
+                       status = MPI_IOCSTATUS_SUCCESS;
+               }
 
-               dprintk((KERN_NOTICE "  Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
-                               ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
-                               mf, mr, sc));
-               dprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh"
-                               ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
-                               status, scsi_state, pScsiReply->SCSIStatus,
-                               le32_to_cpu(pScsiReply->IOCLogInfo)));
+               dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
+                       "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
+                       "resid=%d bufflen=%d xfer_cnt=%d\n",
+                       ioc->id, sc->device->id, sc->device->lun,
+                       status, scsi_state, scsi_status, sc->resid,
+                       sc->request_bufflen, xfer_cnt));
 
                if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
-                       copy_sense_data(sc, hd, mf, pScsiReply);
-                
+                       mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
+
                /*
                 *  Look for + dump FCP ResponseInfo[]!
                 */
-               if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
-                       printk(KERN_NOTICE "  FCP_ResponseInfo=%08xh\n",
+               if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
+                   pScsiReply->ResponseInfo) {
+                       printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
+                       "FCP_ResponseInfo=%08xh\n",
+                       ioc->id, sc->device->id, sc->device->lun,
                        le32_to_cpu(pScsiReply->ResponseInfo));
                }
 
@@ -821,7 +661,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                         * But not: DID_BUS_BUSY lest one risk
                         * killing interrupt handler:-(
                         */
-                       sc->result = STS_BUSY;
+                       sc->result = SAM_STAT_BUSY;
                        break;
 
                case MPI_IOCSTATUS_SCSI_INVALID_BUS:            /* 0x0041 */
@@ -831,41 +671,89 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
                case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
                        /* Spoof to SCSI Selection Timeout! */
-                       sc->result = DID_NO_CONNECT << 16;
+                       if (ioc->bus_type != FC)
+                               sc->result = DID_NO_CONNECT << 16;
+                       /* else fibre, just stall until rescan event */
+                       else
+                               sc->result = DID_REQUEUE << 16;
 
                        if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
                                hd->sel_timeout[pScsiReq->TargetID]++;
+
+                       vdev = sc->device->hostdata;
+                       if (!vdev)
+                               break;
+                       vtarget = vdev->vtarget;
+                       if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
+                               mptscsih_issue_sep_command(ioc, vtarget,
+                                   MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
+                               vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
+                       }
                        break;
 
-               case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
                case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
+                       if ( ioc->bus_type == SAS ) {
+                               u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
+                               if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+                                       u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+                                       log_info &=SAS_LOGINFO_MASK;
+                                       if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
+                                               sc->result = (DID_BUS_BUSY << 16);
+                                               break;
+                                       }
+                               }
+                       } else if (ioc->bus_type == FC) {
+                               /*
+                                * The FC IOC may kill a request for variety of
+                                * reasons, some of which may be recovered by a
+                                * retry, some which are unlikely to be
+                                * recovered. Return DID_ERROR instead of
+                                * DID_RESET to permit retry of the command,
+                                * just not an infinite number of them
+                                */
+                               sc->result = DID_ERROR << 16;
+                               break;
+                       }
+
+                       /*
+                        * Allow non-SAS & non-NEXUS_LOSS to drop into below code
+                        */
+
+               case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
                case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
                        /* Linux handles an unsolicited DID_RESET better
                         * than an unsolicited DID_ABORT.
                         */
                        sc->result = DID_RESET << 16;
 
-                       /* GEM Workaround. */
-                       if (hd->is_spi)
-                               mptscsih_no_negotiate(hd, sc->device->id);
                        break;
 
                case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:      /* 0x0049 */
+                       sc->resid = sc->request_bufflen - xfer_cnt;
+                       if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
+                               sc->result=DID_SOFT_ERROR << 16;
+                       else /* Sufficient data transfer occurred */
+                               sc->result = (DID_OK << 16) | scsi_status;
+                       dreplyprintk((KERN_NOTICE
+                           "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
+                       break;
+
                case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
                        /*
                         *  Do upfront check for valid SenseData and give it
                         *  precedence!
                         */
-                       scsi_status = pScsiReply->SCSIStatus;
                        sc->result = (DID_OK << 16) | scsi_status;
-                       xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
                        if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
                                /* Have already saved the status and sense data
                                 */
                                ;
                        } else {
-                               if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) {
-                                       sc->result = DID_SOFT_ERROR << 16;
+                               if (xfer_cnt < sc->underflow) {
+                                       if (scsi_status == SAM_STAT_BUSY)
+                                               sc->result = SAM_STAT_BUSY;
+                                       else
+                                               sc->result = DID_SOFT_ERROR << 16;
                                }
                                if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
                                        /* What to do?
@@ -878,25 +766,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                }
                        }
 
-                       /* Give report and update residual count.
-                        */
-                       dprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
+                       dreplyprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
                                        sc->underflow));
-                       dprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
-
-                       sc->resid = sc->request_bufflen - xfer_cnt;
-                       dprintk((KERN_NOTICE "  SET sc->resid=%02xh\n", sc->resid));
-                       
+                       dreplyprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
                        /* Report Queue Full
                         */
                        if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
                                mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
-                       
+
                        break;
 
+               case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:           /* 0x0044 */
+                       sc->resid=0;
                case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
                case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
-                       sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
+                       if (scsi_status == MPI_SCSI_STATUS_BUSY)
+                               sc->result = (DID_BUS_BUSY << 16) | scsi_status;
+                       else
+                               sc->result = (DID_OK << 16) | scsi_status;
                        if (scsi_state == 0) {
                                ;
                        } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
@@ -940,7 +827,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        break;
 
                case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:         /* 0x0047 */
-                               sc->result = DID_SOFT_ERROR << 16;
+                       sc->result = DID_SOFT_ERROR << 16;
                        break;
 
                case MPI_IOCSTATUS_INVALID_FUNCTION:            /* 0x0001 */
@@ -950,7 +837,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:      /* 0x0006 */
                case MPI_IOCSTATUS_INVALID_FIELD:               /* 0x0007 */
                case MPI_IOCSTATUS_INVALID_STATE:               /* 0x0008 */
-               case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:           /* 0x0044 */
                case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
                case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:       /* 0x004A */
                default:
@@ -962,110 +848,25 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
                }       /* switch(status) */
 
-               dprintk((KERN_NOTICE "  sc->result set to %08xh\n", sc->result));
+               dreplyprintk((KERN_NOTICE "  sc->result is %08xh\n", sc->result));
        } /* end of address reply case */
 
        /* Unmap the DMA buffers, if any. */
        if (sc->use_sg) {
                pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
-                           sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
+                           sc->use_sg, sc->sc_data_direction);
        } else if (sc->request_bufflen) {
-               scPrivate       *my_priv;
-
-               my_priv = (scPrivate *) &sc->SCp;
-               pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
-                          sc->request_bufflen,
-                          scsi_to_pci_dma_dir(sc->sc_data_direction));
+               pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
+                               sc->request_bufflen, sc->sc_data_direction);
        }
 
-       hd->ScsiLookup[req_idx] = NULL;
-
        sc->scsi_done(sc);              /* Issue the command callback */
 
        /* Free Chain buffers */
-       mptscsih_freeChainBuffers(hd, req_idx);
+       mptscsih_freeChainBuffers(ioc, req_idx);
        return 1;
 }
 
-/*
- * Flush all commands on the doneQ.
- * Lock Q when deleting/adding members
- * Lock io_request_lock for OS callback.
- */
-static void
-flush_doneQ(MPT_SCSI_HOST *hd)
-{
-       MPT_DONE_Q      *buffer;
-       Scsi_Cmnd       *SCpnt;
-       unsigned long    flags;
-
-       /* Flush the doneQ.
-        */
-       dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n"));
-       while (1) {
-               spin_lock_irqsave(&hd->freedoneQlock, flags);
-               if (Q_IS_EMPTY(&hd->doneQ)) {
-                       spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-                       break;
-               }
-
-               buffer = hd->doneQ.head;
-               /* Delete from Q
-                */
-               Q_DEL_ITEM(buffer);
-
-               /* Set the Scsi_Cmnd pointer
-                */
-               SCpnt = (Scsi_Cmnd *) buffer->argp;
-               buffer->argp = NULL;
-
-               /* Add to the freeQ
-                */
-               Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-               spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-
-               /* Do the OS callback.
-                */
-               SCpnt->scsi_done(SCpnt);
-       }
-
-       return;
-}
-
-/*
- * Search the doneQ for a specific command. If found, delete from Q.
- * Calling function will finish processing.
- */
-static void
-search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt)
-{
-       unsigned long    flags;
-       MPT_DONE_Q      *buffer;
-
-       spin_lock_irqsave(&hd->freedoneQlock, flags);
-       if (!Q_IS_EMPTY(&hd->doneQ)) {
-               buffer = hd->doneQ.head;
-               do {
-                       Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp;
-                       if (SCpnt == sc) {
-                               Q_DEL_ITEM(buffer);
-                               SCpnt->result = sc->result;
-
-                               /* Set the Scsi_Cmnd pointer
-                                */
-                               buffer->argp = NULL;
-
-                               /* Add to the freeQ
-                                */
-                               Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-                               break;
-                       }
-               } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ);
-       }
-       spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-       return;
-}
-
 /*
  *     mptscsih_flush_running_cmds - For each command found, search
  *             Scsi_Host instance taskQ and reply to OS.
@@ -1079,12 +880,11 @@ search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt)
 static void
 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 {
-       Scsi_Cmnd       *SCpnt;
+       MPT_ADAPTER *ioc = hd->ioc;
+       struct scsi_cmnd        *SCpnt;
        MPT_FRAME_HDR   *mf;
-       MPT_DONE_Q      *buffer;
        int              ii;
-       int              max = hd->ioc->req_depth;
-       unsigned long    flags;
+       int              max = ioc->req_depth;
 
        dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
        for (ii= 0; ii < max; ii++) {
@@ -1093,74 +893,41 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
                        /* Command found.
                         */
 
-                       /* Search pendingQ, if found,
-                        * delete from Q.
-                        */
-                       mptscsih_search_pendingQ(hd, ii);
-
                        /* Null ScsiLookup index
                         */
                        hd->ScsiLookup[ii] = NULL;
 
-                       mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);
+                       mf = MPT_INDEX_2_MFPTR(ioc, ii);
                        dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
                                        mf, SCpnt));
 
+                       /* Free Chain buffers */
+                       mptscsih_freeChainBuffers(ioc, ii);
+
+                       /* Free Message frames */
+                       mpt_free_msg_frame(ioc, mf);
+
+                       if ((unsigned char *)mf != SCpnt->host_scribble)
+                               continue;
+
                        /* Set status, free OS resources (SG DMA buffers)
                         * Do OS callback
-                        * Free driver resources (chain, msg buffers)
                         */
-                       if (scsi_device_online(SCpnt->device)) {
-                               if (SCpnt->use_sg) {
-                                       pci_unmap_sg(hd->ioc->pcidev,
-                                               (struct scatterlist *) SCpnt->request_buffer,
-                                               SCpnt->use_sg,
-                                               scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-                               } else if (SCpnt->request_bufflen) {
-                                       scPrivate       *my_priv;
-
-                                       my_priv = (scPrivate *) &SCpnt->SCp;
-                                       pci_unmap_single(hd->ioc->pcidev,
-                                               (dma_addr_t)(ulong)my_priv->p1,
-                                               SCpnt->request_bufflen,
-                                               scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-                               }
+                       if (SCpnt->use_sg) {
+                               pci_unmap_sg(ioc->pcidev,
+                                       (struct scatterlist *) SCpnt->request_buffer,
+                                       SCpnt->use_sg,
+                                       SCpnt->sc_data_direction);
+                       } else if (SCpnt->request_bufflen) {
+                               pci_unmap_single(ioc->pcidev,
+                                       SCpnt->SCp.dma_handle,
+                                       SCpnt->request_bufflen,
+                                       SCpnt->sc_data_direction);
                        }
                        SCpnt->result = DID_RESET << 16;
                        SCpnt->host_scribble = NULL;
 
-                       /* Free Chain buffers */
-                       mptscsih_freeChainBuffers(hd, ii);
-
-                       /* Free Message frames */
-                       mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
-
-#if 1
-                       /* Post to doneQ, do not reply until POST phase
-                        * of reset handler....prevents new commands from
-                        * being queued.
-                        */
-                       spin_lock_irqsave(&hd->freedoneQlock, flags);
-                       if (!Q_IS_EMPTY(&hd->freeQ)) {
-                               buffer = hd->freeQ.head;
-                               Q_DEL_ITEM(buffer);
-
-                               /* Set the Scsi_Cmnd pointer
-                                */
-                               buffer->argp = (void *)SCpnt;
-
-                               /* Add to the doneQ
-                                */
-                               Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
-                               spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-                       } else {
-                               spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-                               SCpnt->scsi_done(SCpnt);
-                       }
-#else
                        SCpnt->scsi_done(SCpnt);        /* Issue the command callback */
-#endif
-
                }
        }
 
@@ -1171,165 +938,71 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
  *     mptscsih_search_running_cmds - Delete any commands associated
  *             with the specified target and lun. Function called only
  *             when a lun is disable by mid-layer.
- *             Do NOT access the referenced Scsi_Cmnd structure or
+ *             Do NOT access the referenced scsi_cmnd structure or
  *             members. Will cause either a paging or NULL ptr error.
- *     @hd: Pointer to a SCSI HOST structure
- *     @target: target id
- *     @lun: lun
+ *             (BUT, BUT, BUT, the code does reference it! - mdr)
+ *      @hd: Pointer to a SCSI HOST structure
+ *     @vdevice: per device private data
  *
  *     Returns: None.
  *
  *     Called from slave_destroy.
  */
 static void
-mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
+mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 {
        SCSIIORequest_t *mf = NULL;
        int              ii;
        int              max = hd->ioc->req_depth;
+       struct scsi_cmnd *sc;
 
        dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
-                       target, lun, max));
+                       vdevice->vtarget->target_id, vdevice->lun, max));
 
        for (ii=0; ii < max; ii++) {
-               if (hd->ScsiLookup[ii] != NULL) {
+               if ((sc = hd->ScsiLookup[ii]) != NULL) {
 
                        mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
-
+                       if (mf == NULL)
+                               continue;
                        dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
                                        hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
-
-                       if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
+                       if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
                                continue;
 
                        /* Cleanup
                         */
                        hd->ScsiLookup[ii] = NULL;
-                       mptscsih_freeChainBuffers(hd, ii);
-                       mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, (MPT_FRAME_HDR *)mf);
+                       mptscsih_freeChainBuffers(hd->ioc, ii);
+                       mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
+                       if ((unsigned char *)mf != sc->host_scribble)
+                               continue;
+                       if (sc->use_sg) {
+                               pci_unmap_sg(hd->ioc->pcidev,
+                               (struct scatterlist *) sc->request_buffer,
+                                       sc->use_sg,
+                                       sc->sc_data_direction);
+                       } else if (sc->request_bufflen) {
+                               pci_unmap_single(hd->ioc->pcidev,
+                                       sc->SCp.dma_handle,
+                                       sc->request_bufflen,
+                                       sc->sc_data_direction);
+                       }
+                       sc->host_scribble = NULL;
+                       sc->result = DID_NO_CONNECT << 16;
+                       sc->scsi_done(sc);
                }
        }
-
        return;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mptscsih_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
-mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
-{
-       MPT_FRAME_HDR   *chain;
-       u8              *mem;
-       unsigned long   flags;
-       int             sz, ii, num_chain;
-       int             scale, num_sge;
-
-       /* chain buffer allocation done from PrimeIocFifos */   
-       if (hd->ioc->fifo_pool == NULL) 
-               return -1;
-       
-       hd->ChainBuffer = hd->ioc->chain_alloc;
-       hd->ChainBufferDMA = hd->ioc->chain_alloc_dma;
-       
-       dprintk((KERN_INFO "  ChainBuffer    @ %p(%p), sz=%d\n",
-                hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, hd->ioc->chain_alloc_sz));
-               
-       /* ReqToChain size must equal the req_depth
-        * index = req_idx
-        */
-       if (hd->ReqToChain == NULL) {
-               sz = hd->ioc->req_depth * sizeof(int);
-               mem = kmalloc(sz, GFP_ATOMIC);
-               if (mem == NULL)
-                       return -1;
-
-               hd->ReqToChain = (int *) mem;
-       }
-       for (ii = 0; ii < hd->ioc->req_depth; ii++)
-               hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
-
-       /* 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
-        *
-        * num_sge = num sge in request frame + last chain buffer
-        * scale = num sge per chain buffer if no chain element
-        */
-       scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
-       if (sizeof(dma_addr_t) == sizeof(u64))
-               num_sge =  scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
-       else
-               num_sge =  1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
-
-       num_chain = 1;
-       while (hd->max_sge - num_sge > 0) {
-               num_chain++;
-               num_sge += (scale - 1);
-       }
-       num_chain++;
-
-       if ((int) hd->ioc->chip_type > (int) FC929)
-               num_chain *= MPT_SCSI_CAN_QUEUE;
-       else
-               num_chain *= MPT_FC_CAN_QUEUE;
-
-       hd->num_chain = num_chain;
-
-       sz = num_chain * sizeof(int);
-       if (hd->ChainToChain == NULL) {
-               mem = kmalloc(sz, GFP_ATOMIC);
-               if (mem == NULL)
-                       return -1;
-
-               hd->ChainToChain = (int *) mem;
-       } else {
-               mem = (u8 *) hd->ChainToChain;
-       }
-       memset(mem, 0xFF, sz);
-
-
-       /* Initialize the free chain Q.
-        */
-       if (init) {
-               spin_lock_init(&hd->FreeChainQlock);
-       }
-
-       spin_lock_irqsave (&hd->FreeChainQlock, flags);
-       Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);
-
-       /* Post the chain buffers to the FreeChainQ.
-        */
-       mem = (u8 *)hd->ChainBuffer;
-       for (ii=0; ii < num_chain; ii++) {
-               chain = (MPT_FRAME_HDR *) mem;
-               Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);
-               mem += hd->ioc->req_sz;
-       }
-       spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
-
-       return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Hack! It might be nice to report if a device is returning QUEUE_FULL
- *  but maybe not each and every time...
- */
-static long last_queue_full = 0;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mptscsih_report_queue_full - Report QUEUE_FULL status returned
  *     from a SCSI target device.
- *     @sc: Pointer to Scsi_Cmnd structure
+ *     @sc: Pointer to scsi_cmnd structure
  *     @pScsiReply: Pointer to SCSIIOReply_t
  *     @pScsiReq: Pointer to original SCSI request
  *
@@ -1338,363 +1011,25 @@ static long last_queue_full = 0;
  *     printk() API call, not more than once every 10 seconds.
  */
 static void
-mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
+mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
 {
        long time = jiffies;
+       MPT_SCSI_HOST           *hd;
 
-       if (time - last_queue_full > 10 * HZ) {
-               char *ioc_str = "ioc?";
+       if (sc->device == NULL)
+               return;
+       if (sc->device->host == NULL)
+               return;
+       if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
+               return;
 
-               if (sc->device && sc->device->host != NULL && sc->device->host->hostdata != NULL)
-                       ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name;
+       if (time - hd->last_queue_full > 10 * HZ) {
                dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
-                               ioc_str, 0, sc->device->id, sc->device->lun));
-               last_queue_full = time;
+                               hd->ioc->name, 0, sc->device->id, sc->device->lun));
+               hd->last_queue_full = time;
        }
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static char *info_kbuf = NULL;
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mptscsih_probe - Installs scsi devices per bus.
- *     @pdev: Pointer to pci_dev structure
- *
- *     Returns 0 for success, non-zero for failure.
- *
- */
-
-static int
-mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       struct Scsi_Host        *sh;
-       MPT_SCSI_HOST           *hd;
-       MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
-       MPT_DONE_Q              *freedoneQ;
-       unsigned long            flags;
-       int                      sz, ii;
-       int                      numSGE = 0;
-       int                      scale;
-       int                      ioc_cap;
-       u8                      *mem;
-       int                     error=0;
-
-
-       /* 20010202 -sralston
-        *  Added sanity check on readiness of the MPT adapter.
-        */
-       if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
-               printk(MYIOC_s_WARN_FMT
-                 "Skipping because it's not operational!\n",
-                 ioc->name);
-               return -ENODEV;
-       }
-
-       if (!ioc->active) {
-               printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
-                 ioc->name);
-               return -ENODEV;
-       }
-
-       /*  Sanity check - ensure at least 1 port is INITIATOR capable
-        */
-       ioc_cap = 0;
-       for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-               if (ioc->pfacts[ii].ProtocolFlags &
-                   MPI_PORTFACTS_PROTOCOL_INITIATOR)
-                       ioc_cap ++;
-       }
-
-       if (!ioc_cap) {
-               printk(MYIOC_s_WARN_FMT
-                       "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
-                       ioc->name, ioc);
-               return -ENODEV;
-       }
-
-       sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));
-        
-       if (!sh) {
-               printk(MYIOC_s_WARN_FMT
-                       "Unable to register controller with SCSI subsystem\n",
-                       ioc->name);
-                return -1;
-        }
-       
-       spin_lock_irqsave(&ioc->FreeQlock, flags);
-
-       /* Attach the SCSI Host to the IOC structure
-        */
-       ioc->sh = sh;
-
-       sh->io_port = 0;
-       sh->n_io_port = 0;
-       sh->irq = 0;
-
-       /* set 16 byte cdb's */
-       sh->max_cmd_len = 16;
-
-       /* Yikes!  This is important!
-        * Otherwise, by default, linux
-        * only scans target IDs 0-7!
-        * pfactsN->MaxDevices unreliable
-        * (not supported in early
-        *      versions of the FW).
-        * max_id = 1 + actual max id,
-        * max_lun = 1 + actual last lun,
-        *      see hosts.h :o(
-        */
-       if ((int)ioc->chip_type > (int)FC929) {
-               sh->max_id = MPT_MAX_SCSI_DEVICES;
-       } else {
-       /* For FC, increase the queue depth
-        * from MPT_SCSI_CAN_QUEUE (31)
-        * to MPT_FC_CAN_QUEUE (63).
-        */
-               sh->can_queue = MPT_FC_CAN_QUEUE;
-               sh->max_id =
-                 MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
-       }
-               
-       sh->max_lun = MPT_LAST_LUN + 1;
-       sh->max_sectors = MPT_SCSI_MAX_SECTORS;
-       sh->max_channel = 0;
-       sh->this_id = ioc->pfacts[0].PortSCSIID;
-               
-       /* Required entry.
-        */
-       sh->unique_id = ioc->id;
-
-       /* Verify that we won't exceed the maximum
-        * number of chain buffers
-        * We can optimize:  ZZ = req_sz/sizeof(SGE)
-        * For 32bit SGE's:
-        *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
-        *               + (req_sz - 64)/sizeof(SGE)
-        * A slightly different algorithm is required for
-        * 64bit SGEs.
-        */
-       scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
-       if (sizeof(dma_addr_t) == sizeof(u64)) {
-               numSGE = (scale - 1) *
-                 (ioc->facts.MaxChainDepth-1) + scale +
-                 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
-                 sizeof(u32));
-       } else {
-               numSGE = 1 + (scale - 1) *
-                 (ioc->facts.MaxChainDepth-1) + scale +
-                 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
-                 sizeof(u32));
-       }
-               
-       if (numSGE < sh->sg_tablesize) {
-               /* Reset this value */
-               dprintk((MYIOC_s_INFO_FMT
-                 "Resetting sg_tablesize to %d from %d\n",
-                 ioc->name, numSGE, sh->sg_tablesize));
-               sh->sg_tablesize = numSGE;
-       }
-
-       /* Set the pci device pointer in Scsi_Host structure.
-        */
-       scsi_set_device(sh, &ioc->pcidev->dev);
-
-       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
-       hd = (MPT_SCSI_HOST *) sh->hostdata;
-       hd->ioc = ioc;
-       hd->max_sge = sh->sg_tablesize;
-
-       if ((int)ioc->chip_type > (int)FC929)
-       hd->is_spi = 1;
-
-       if (DmpService && (ioc->chip_type == FC919 ||
-         ioc->chip_type == FC929)) {
-               hd->is_multipath = 1;
-       }
-
-       /* SCSI needs Scsi_Cmnd lookup table!
-        * (with size equal to req_depth*PtrSz!)
-        */
-       sz = hd->ioc->req_depth * sizeof(void *);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL) {
-               error = -ENOMEM;
-               goto mptscsih_probe_failed;
-       }
-
-       memset(mem, 0, sz);
-       hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
-       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
-                ioc->name, hd->ScsiLookup, sz));
-               
-       if (mptscsih_initChainBuffers(hd, 1) < 0) {
-               error = -EINVAL;
-               goto mptscsih_probe_failed;
-       }
-
-       /* Allocate memory for free and doneQ's
-        */
-       sz = sh->can_queue * sizeof(MPT_DONE_Q);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL) {
-               error = -ENOMEM;
-               goto mptscsih_probe_failed;
-       }
-
-       memset(mem, 0xFF, sz);
-       hd->memQ = mem;
-
-       /* Initialize the free, done and pending Qs.
-        */
-       Q_INIT(&hd->freeQ, MPT_DONE_Q);
-       Q_INIT(&hd->doneQ, MPT_DONE_Q);
-       Q_INIT(&hd->pendingQ, MPT_DONE_Q);
-       spin_lock_init(&hd->freedoneQlock);
-
-       mem = hd->memQ;
-       for (ii=0; ii < sh->can_queue; ii++) {
-               freedoneQ = (MPT_DONE_Q *) mem;
-               Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
-               mem += sizeof(MPT_DONE_Q);
-       }
-
-       /* Initialize this Scsi_Host
-        * internal task Q.
-        */
-       Q_INIT(&hd->taskQ, MPT_FRAME_HDR);
-       hd->taskQcnt = 0;
-               
-       /* Allocate memory for the device structures.
-        * A non-Null pointer at an offset
-        * indicates a device exists.
-        * max_id = 1 + maximum id (hosts.h)
-        */
-       sz = sh->max_id * sizeof(void *);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL) {
-               error = -ENOMEM;
-               goto mptscsih_probe_failed;
-       }
-
-       memset(mem, 0, sz);
-       hd->Targets = (VirtDevice **) mem;
-
-       dprintk((KERN_INFO
-         "  Targets @ %p, sz=%d\n", hd->Targets, sz));
-
-       /* Clear the TM flags
-        */
-       hd->tmPending = 0;
-       hd->tmState = TM_STATE_NONE;
-       hd->resetPending = 0;
-       hd->abortSCpnt = NULL;
-       hd->tmPtr = NULL;
-       hd->numTMrequests = 0;
-               
-       /* Clear the pointer used to store
-        * single-threaded commands, i.e., those
-        * issued during a bus scan, dv and
-        * configuration pages.
-        */
-       hd->cmdPtr = NULL;
-
-       /* Initialize this SCSI Hosts' timers
-        * To use, set the timer expires field
-        * and add_timer
-        */
-       init_timer(&hd->timer);
-       hd->timer.data = (unsigned long) hd;
-       hd->timer.function = mptscsih_timer_expired;
-
-       init_timer(&hd->TMtimer);
-       hd->TMtimer.data = (unsigned long) hd;
-       hd->TMtimer.function = mptscsih_taskmgmt_timeout;
-       hd->qtag_tick = jiffies;
-
-       /* Moved Earlier Pam D */
-       /* ioc->sh = sh;        */
-
-#ifdef MPTSCSIH_DBG_TIMEOUT
-       hd->ioc->timeout_hard = 0;
-       hd->ioc->timeout_delta = 30 * HZ;
-       hd->ioc->timeout_maxcnt = 0;
-       hd->ioc->timeout_cnt = 0;
-       for (ii=0; ii < 8; ii++)
-               foo_to[ii] = NULL;
-#endif
-       if (hd->is_spi) {
-               /* Update with the driver setup
-                * values.
-                */
-               if (hd->ioc->spi_data.maxBusWidth >
-                 driver_setup.max_width) {
-                       hd->ioc->spi_data.maxBusWidth =
-                         driver_setup.max_width;
-               }
-
-               if (hd->ioc->spi_data.minSyncFactor <
-                 driver_setup.min_sync_fac) {
-                       hd->ioc->spi_data.minSyncFactor =
-                         driver_setup.min_sync_fac;
-               }
-
-               if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) {
-                       hd->ioc->spi_data.maxSyncOffset = 0;
-               }
-
-               hd->ioc->spi_data.Saf_Te = driver_setup.saf_te;
-
-               hd->negoNvram = 0;
-#ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-               hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
-#endif
-               if (driver_setup.dv == 0) {
-                       hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
-               }
-
-               hd->ioc->spi_data.forceDv = 0;
-               for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-                       hd->ioc->spi_data.dvStatus[ii] =
-                         MPT_SCSICFG_NEGOTIATE;
-               }
-
-               if (hd->negoNvram == 0) {
-                       for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
-                               hd->ioc->spi_data.dvStatus[ii] |=
-                                 MPT_SCSICFG_DV_NOT_DONE;
-               }
-
-               ddvprintk((MYIOC_s_INFO_FMT
-                       "dv %x width %x factor %x saf_te %x\n",
-                       hd->ioc->name, driver_setup.dv,
-                       driver_setup.max_width,
-                       driver_setup.min_sync_fac,
-                       driver_setup.saf_te));
-       }
-
-       mpt_scsi_hosts++;
-
-       error = scsi_add_host (sh, &ioc->pcidev->dev);
-       if(error) {
-               dprintk((KERN_ERR MYNAM
-                 "scsi_add_host failed\n"));
-               goto mptscsih_probe_failed;
-       }
-
-       scsi_scan_host(sh);
-       return 0;
-
-mptscsih_probe_failed:
-
-       mptscsih_remove(pdev);
-       return error;
-
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mptscsih_remove - Removed scsi devices
@@ -1702,115 +1037,53 @@ mptscsih_probe_failed:
  *
  *
  */
-static void
+void
 mptscsih_remove(struct pci_dev *pdev)
 {
        MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
        struct Scsi_Host        *host = ioc->sh;
        MPT_SCSI_HOST           *hd;
-       int                     count;
-       unsigned long           flags;
+       int sz1;
 
-       if(!host)
+       if(!host) {
+               mpt_detach(pdev);
                return;
-
-       scsi_remove_host(host);
-
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-       /* Check DV thread active */
-       count = 10 * HZ;
-       spin_lock_irqsave(&dvtaskQ_lock, flags);
-       if (dvtaskQ_active) {
-               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-               while(dvtaskQ_active && --count) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
-               }
-       } else {
-               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
        }
-       if (!count)
-               printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
-#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
-       else
-               printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
-#endif
-#endif
-
-       hd = (MPT_SCSI_HOST *)host->hostdata;
-       if (hd != NULL) {
-               int sz1, sz2, sz3, sztarget=0;
-               int szr2chain = 0;
-               int szc2chain = 0;
-               int szQ = 0;
 
-               mptscsih_shutdown(&pdev->dev);
-
-               sz1 = sz2 = sz3 = 0;
-
-               if (hd->ScsiLookup != NULL) {
-                       sz1 = hd->ioc->req_depth * sizeof(void *);
-                       kfree(hd->ScsiLookup);
-                       hd->ScsiLookup = NULL;
-               }
+       scsi_remove_host(host);
 
-               if (hd->ReqToChain != NULL) {
-                       szr2chain = hd->ioc->req_depth * sizeof(int);
-                       kfree(hd->ReqToChain);
-                       hd->ReqToChain = NULL;
-               }
+       if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
+               return;
 
-               if (hd->ChainToChain != NULL) {
-                       szc2chain = hd->num_chain * sizeof(int);
-                       kfree(hd->ChainToChain);
-                       hd->ChainToChain = NULL;
-               }
+       mptscsih_shutdown(pdev);
 
-               if (hd->memQ != NULL) {
-                       szQ = host->can_queue * sizeof(MPT_DONE_Q);
-                       kfree(hd->memQ);
-                       hd->memQ = NULL;
-               }
+       sz1=0;
 
-               if (hd->Targets != NULL) {
-                       int max, ii;
+       if (hd->ScsiLookup != NULL) {
+               sz1 = hd->ioc->req_depth * sizeof(void *);
+               kfree(hd->ScsiLookup);
+               hd->ScsiLookup = NULL;
+       }
 
-                       /*
-                        * Free any target structures that were allocated.
-                        */
-                       if (hd->is_spi) {
-                               max = MPT_MAX_SCSI_DEVICES;
-                       } else {
-                               max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
-                       }
-                       for (ii=0; ii < max; ii++) {
-                               if (hd->Targets[ii]) {
-                                       kfree(hd->Targets[ii]);
-                                       hd->Targets[ii] = NULL;
-                                       sztarget += sizeof(VirtDevice);
-                               }
-                       }
+       /*
+        * Free pointer array.
+        */
+       kfree(hd->Targets);
+       hd->Targets = NULL;
 
-                       /*
-                        * Free pointer array.
-                        */
-                       sz3 = max * sizeof(void *);
-                       kfree(hd->Targets);
-                       hd->Targets = NULL;
-               }
+       dprintk((MYIOC_s_INFO_FMT
+           "Free'd ScsiLookup (%d) memory\n",
+           hd->ioc->name, sz1));
 
-               dprintk((MYIOC_s_INFO_FMT
-                 "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",
-                 hd->ioc->name, sz1, szchain, sz3, sztarget));
-               dprintk(("Free'd done and free Q (%d) memory\n", szQ));
+       kfree(hd->info_kbuf);
 
-               /* NULL the Scsi_Host pointer
-                */
-               hd->ioc->sh = NULL;
-       }
+       /* NULL the Scsi_Host pointer
+        */
+       hd->ioc->sh = NULL;
 
        scsi_host_put(host);
-       mpt_scsi_hosts--;
+
+       mpt_detach(pdev);
 
 }
 
@@ -1819,10 +1092,10 @@ mptscsih_remove(struct pci_dev *pdev)
  *     mptscsih_shutdown - reboot notifier
  *
  */
-static void
-mptscsih_shutdown(struct device * dev)
+void
+mptscsih_shutdown(struct pci_dev *pdev)
 {
-       MPT_ADAPTER             *ioc = pci_get_drvdata(to_pci_dev(dev));
+       MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
        struct Scsi_Host        *host = ioc->sh;
        MPT_SCSI_HOST           *hd;
 
@@ -1831,25 +1104,20 @@ mptscsih_shutdown(struct device * dev)
 
        hd = (MPT_SCSI_HOST *)host->hostdata;
 
-       /* Flush the cache of this adapter
-        */
-       if(hd != NULL)
-               mptscsih_synchronize_cache(hd, 0);
-
 }
 
 #ifdef CONFIG_PM
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     mptscsih_suspend - Fusion MPT scsie driver suspend routine.
+ *     mptscsih_suspend - Fusion MPT scsi driver suspend routine.
  *
  *
  */
-static int
-mptscsih_suspend(struct pci_dev *pdev, u32 state)
+int
+mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-       mptscsih_shutdown(&pdev->dev);
-       return 0;
+       mptscsih_shutdown(pdev);
+       return mpt_suspend(pdev,state);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1858,13 +1126,15 @@ mptscsih_suspend(struct pci_dev *pdev, u32 state)
  *
  *
  */
-static int
+int
 mptscsih_resume(struct pci_dev *pdev)
 {
        MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
        struct Scsi_Host        *host = ioc->sh;
        MPT_SCSI_HOST           *hd;
 
+       mpt_resume(pdev);
+
        if(!host)
                return 0;
 
@@ -1872,125 +1142,17 @@ mptscsih_resume(struct pci_dev *pdev)
        if(!hd)
                return 0;
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-       {
-       unsigned long lflags;
-       spin_lock_irqsave(&dvtaskQ_lock, lflags);
-       if (!dvtaskQ_active) {
-               dvtaskQ_active = 1;
-               spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-               MPT_INIT_WORK(&mptscsih_dvTask,
-                 mptscsih_domainValidation, (void *) hd);
-               SCHEDULE_TASK(&mptscsih_dvTask);
-       } else {
-               spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-       }
-       }
-#endif
        return 0;
 }
 
 #endif
 
-static struct mpt_pci_driver mptscsih_driver = {
-       .probe          = mptscsih_probe,
-       .remove         = mptscsih_remove,
-       .shutdown       = mptscsih_shutdown,
-#ifdef CONFIG_PM
-       .suspend        = mptscsih_suspend,
-       .resume         = mptscsih_resume,
-#endif
-};
-
-
-/*  SCSI host fops start here...  */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mptscsih_init - Register MPT adapter(s) as SCSI host(s) with
- *     linux scsi mid-layer.
- *
- *     Returns 0 for success, non-zero for failure.
- */
-static int __init
-mptscsih_init(void)
-{
-
-       show_mptmod_ver(my_NAME, my_VERSION);
-
-       ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
-       ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
-       ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
-
-       if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
-               dprintk((KERN_INFO MYNAM
-                 ": Registered for IOC event notifications\n"));
-       }
-
-       if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
-               dprintk((KERN_INFO MYNAM
-                 ": Registered for IOC reset notifications\n"));
-       }
-
-#ifdef MODULE
-       /* Evaluate the command line arguments, if any */
-       if (mptscsih)
-               mptscsih_setup(mptscsih);
-#endif
-
-       if(mpt_device_driver_register(&mptscsih_driver,
-         MPTSCSIH_DRIVER) != 0 ) {
-               dprintk((KERN_INFO MYNAM
-               ": failed to register dd callbacks\n"));
-       }
-
-       return 0;
-
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mptscsih_exit - Unregisters MPT adapter(s)
- *
- */
-static void __exit
-mptscsih_exit(void)
-{
-       MPT_ADAPTER     *ioc;
-
-       /* removing devices */
-       for(ioc = mpt_adapter_find_first(); ioc != NULL;
-         ioc = mpt_adapter_find_next(ioc)) {
-               if ((ioc->last_state != MPI_IOC_STATE_OPERATIONAL) ||
-                 (ioc->sh == NULL))
-                       continue;
-               mptscsih_remove(ioc->pcidev);
-       }
-
-       mpt_reset_deregister(ScsiDoneCtx);
-       dprintk((KERN_INFO MYNAM
-         ": Deregistered for IOC reset notifications\n"));
-
-       mpt_event_deregister(ScsiDoneCtx);
-       dprintk((KERN_INFO MYNAM
-         ": Deregistered for IOC event notifications\n"));
-
-       mpt_device_driver_deregister(MPTSCSIH_DRIVER);
-       mpt_deregister(ScsiScanDvCtx);
-       mpt_deregister(ScsiTaskCtx);
-       mpt_deregister(ScsiDoneCtx);
-
-       if (info_kbuf != NULL)
-               kfree(info_kbuf);
-
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_info - Return information about MPT adapter
  *     @SChost: Pointer to Scsi_Host structure
  *
- *     (linux Scsi_Host_Template.info routine)
+ *     (linux scsi_host_template.info routine)
  *
  *     Returns pointer to buffer where information was written.
  */
@@ -2000,18 +1162,19 @@ mptscsih_info(struct Scsi_Host *SChost)
        MPT_SCSI_HOST *h;
        int size = 0;
 
-       if (info_kbuf == NULL)
-               if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
-                       return info_kbuf;
-
        h = (MPT_SCSI_HOST *)SChost->hostdata;
-       info_kbuf[0] = '\0';
+
        if (h) {
-               mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
-               info_kbuf[size-1] = '\0';
+               if (h->info_kbuf == NULL)
+                       if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
+                               return h->info_kbuf;
+               h->info_kbuf[0] = '\0';
+
+               mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
+               h->info_kbuf[size-1] = '\0';
        }
 
-       return info_kbuf;
+       return h->info_kbuf;
 }
 
 struct info_str {
@@ -2021,7 +1184,8 @@ struct info_str {
        int   pos;
 };
 
-static void copy_mem_info(struct info_str *info, char *data, int len)
+static void
+mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
 {
        if (info->pos + len > info->length)
                len = info->length - info->pos;
@@ -2042,7 +1206,8 @@ static void copy_mem_info(struct info_str *info, char *data, int len)
        }
 }
 
-static int copy_info(struct info_str *info, char *fmt, ...)
+static int
+mptscsih_copy_info(struct info_str *info, char *fmt, ...)
 {
        va_list args;
        char buf[81];
@@ -2052,11 +1217,12 @@ static int copy_info(struct info_str *info, char *fmt, ...)
        len = vsprintf(buf, fmt, args);
        va_end(args);
 
-       copy_mem_info(info, buf, len);
+       mptscsih_copy_mem_info(info, buf, len);
        return len;
 }
 
-static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
+static int
+mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
 {
        struct info_str info;
 
@@ -2065,252 +1231,107 @@ static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int le
        info.offset     = offset;
        info.pos        = 0;
 
-       copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
-       copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
-       copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
-       copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
+       mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
+       mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
+       mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
+       mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
 
        return ((info.pos > info.offset) ? info.pos - info.offset : 0);
 }
 
-#ifndef MPTSCSIH_DBG_TIMEOUT
-static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len)
-{
-       /* Not yet implemented */
-       return len;
-}
-#else
-#define is_digit(c)    ((c) >= '0' && (c) <= '9')
-#define digit_to_bin(c)        ((c) - '0')
-#define is_space(c)    ((c) == ' ' || (c) == '\t')
-
-#define UC_DBG_TIMEOUT         0x01
-#define UC_DBG_HARDRESET       0x02
-
-static int skip_spaces(char *ptr, int len)
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *     mptscsih_proc_info - Return information about MPT adapter
+ *     @host:   scsi host struct
+ *     @buffer: if write, user data; if read, buffer for user
+ *     @start: returns the buffer address
+ *     @offset: if write, 0; if read, the current offset into the buffer from
+ *              the previous read.
+ *     @length: if write, return length;
+ *     @func:   write = 1; read = 0
+ *
+ *     (linux scsi_host_template.info routine)
+ */
+int
+mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
+                       int length, int func)
 {
-       int cnt, c;
-
-       for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --);
+       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
+       MPT_ADAPTER     *ioc = hd->ioc;
+       int size = 0;
 
-       return (len - cnt);
-}
+       if (func) {
+               /*
+                * write is not supported
+                */
+       } else {
+               if (start)
+                       *start = buffer;
 
-static int get_int_arg(char *ptr, int len, ulong *pv)
-{
-       int cnt, c;
-       ulong   v;
-       for (v =  0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) {
-               v = (v * 10) + digit_to_bin(c);
+               size = mptscsih_host_info(ioc, buffer, offset, length);
        }
 
-       if (pv)
-               *pv = v;
-
-       return (len - cnt);
+       return size;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define ADD_INDEX_LOG(req_ent) do { } while(0)
 
-static int is_keyword(char *ptr, int len, char *verb)
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *     mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
+ *     @SCpnt: Pointer to scsi_cmnd structure
+ *     @done: Pointer SCSI mid-layer IO completion function
+ *
+ *     (linux scsi_host_template.queuecommand routine)
+ *     This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest
+ *     from a linux scsi_cmnd request and send it to the IOC.
+ *
+ *     Returns 0. (rtn value discarded by linux scsi mid-layer)
+ */
+int
+mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
-       int verb_len = strlen(verb);
+       MPT_SCSI_HOST           *hd;
+       MPT_FRAME_HDR           *mf;
+       SCSIIORequest_t         *pScsiReq;
+       VirtDevice              *vdev = SCpnt->device->hostdata;
+       int      lun;
+       u32      datalen;
+       u32      scsictl;
+       u32      scsidir;
+       u32      cmd_len;
+       int      my_idx;
+       int      ii;
 
-       if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))
-               return verb_len;
-       else
-               return 0;
-}
-
-#define SKIP_SPACES(min_spaces)                                                \
-       if ((arg_len = skip_spaces(ptr,len)) < (min_spaces))            \
-               return -EINVAL;                                         \
-       ptr += arg_len;                                                 \
-       len -= arg_len;
-
-#define GET_INT_ARG(v)                                                 \
-       if (!(arg_len = get_int_arg(ptr,len, &(v))))                    \
-               return -EINVAL;                                         \
-       ptr += arg_len;                                                 \
-       len -= arg_len;
-
-static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length)
-{
-       char *ptr = buffer;
-       char btmp[24];  /* REMOVE */
-       int arg_len;
-       int len = length;
-       int cmd;
-       ulong number = 1;
-       ulong delta = 10;
-
-       if ((len > 0) && (ptr[len -1] == '\n'))
-               --len;
-
-       if (len < 22) {
-               strncpy(btmp, buffer, len);
-               btmp[len+1]='\0';
-       } else {
-               strncpy(btmp, buffer, 22);
-               btmp[23]='\0';
-       }
-       printk("user_command:  ioc %d, buffer %s, length %d\n",
-                       ioc->id, btmp, length);
-
-       if ((arg_len = is_keyword(ptr, len, "timeout")) != 0)
-               cmd = UC_DBG_TIMEOUT;
-       else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0)
-               cmd = UC_DBG_HARDRESET;
-       else
-               return -EINVAL;
-
-       ptr += arg_len;
-       len -= arg_len;
-
-       switch(cmd) {
-               case UC_DBG_TIMEOUT:
-                       SKIP_SPACES(1);
-                       GET_INT_ARG(number);
-                       SKIP_SPACES(1);
-                       GET_INT_ARG(delta);
-                       break;
-       }
-
-       printk("user_command: cnt=%ld delta=%ld\n", number, delta);
-
-       if (len)
-               return -EINVAL;
-       else {
-               if (cmd == UC_DBG_HARDRESET) {
-                       ioc->timeout_hard = 1;
-               } else if (cmd == UC_DBG_TIMEOUT) {
-                       /* process this command ...
-                        */
-                       ioc->timeout_maxcnt = 0;
-                       ioc->timeout_delta = delta < 2 ? 2 : delta;
-                       ioc->timeout_cnt = 0;
-                       ioc->timeout_maxcnt = number < 8 ? number: 8;
-               }
-       }
-       /* Not yet implemented */
-       return length;
-}
-#endif
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mptscsih_proc_info - Return information about MPT adapter
- *
- *     (linux Scsi_Host_Template.info routine)
- *
- *     buffer: if write, user data; if read, buffer for user
- *     length: if write, return length;
- *     offset: if write, 0; if read, the current offset into the buffer from
- *             the previous read.
- *     hostno: scsi host number
- *     func:   if write = 1; if read = 0
- */
-int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
-                       int length, int func)
-{
-       MPT_ADAPTER     *ioc;
-       MPT_SCSI_HOST   *hd = NULL;
-       int size = 0;
-
-       dprintk(("Called mptscsih_proc_info: hostno=%d, func=%d\n", host->host_no, func));
-       dprintk(("buffer %p, start=%p (%p) offset=%ld length = %d\n",
-                       buffer, start, *start, offset, length));
-
-       for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
-               if ((ioc->sh) && (ioc->sh == host)) {
-                       hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
-                       break;
-               }
-       }
-       if ((ioc == NULL) || (ioc->sh == NULL) || (hd == NULL))
-               return 0;
-
-       if (func) {
-               size = mptscsih_user_command(ioc, buffer, length);
-       } else {
-               if (start)
-                       *start = buffer;
-
-               size = mptscsih_host_info(ioc, buffer, offset, length);
-       }
-
-       return size;
-}
-
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#define ADD_INDEX_LOG(req_ent) do { } while(0)
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
- *     @SCpnt: Pointer to Scsi_Cmnd structure
- *     @done: Pointer SCSI mid-layer IO completion function
- *
- *     (linux Scsi_Host_Template.queuecommand routine)
- *     This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest
- *     from a linux Scsi_Cmnd request and send it to the IOC.
- *
- *     Returns 0. (rtn value discarded by linux scsi mid-layer)
- */
-int
-mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
-{
-       MPT_SCSI_HOST           *hd;
-       MPT_FRAME_HDR           *mf;
-       SCSIIORequest_t         *pScsiReq;
-       VirtDevice              *pTarget;
-       MPT_DONE_Q              *buffer;
-       unsigned long            flags;
-       int      target;
-       int      lun;
-       int      datadir;
-       u32      datalen;
-       u32      scsictl;
-       u32      scsidir;
-       u32      cmd_len;
-       int      my_idx;
-       int      ii;
-       int      rc;
-       int      did_errcode;
-       int      issueCmd;
-
-       did_errcode = 0;
        hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
-       target = SCpnt->device->id;
        lun = SCpnt->device->lun;
        SCpnt->scsi_done = done;
 
-       pTarget = hd->Targets[target];
-
        dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
                        (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
 
        if (hd->resetPending) {
-               /* Prevent new commands from being issued
-                * while reloading the FW. Reset timer to 60 seconds,
-                * as the FW can take some time to come ready.
-                * For New EH, cmds on doneQ posted to FW.
-                */
-               did_errcode = 1;
-               mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));
                dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
                        (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
-               goto did_error;
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+
+       if ((hd->ioc->bus_type == SPI) &&
+           vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
+           mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) {
+               SCpnt->result = DID_NO_CONNECT << 16;
+               done(SCpnt);
+               return 0;
        }
 
        /*
         *  Put together a MPT SCSI request...
         */
-       if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
+       if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
                dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
                                hd->ioc->name));
-               did_errcode = 2;
-               goto did_error;
+               return SCSI_MLQUEUE_HOST_BUSY;
        }
 
        pScsiReq = (SCSIIORequest_t *) mf;
@@ -2319,21 +1340,14 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 
        ADD_INDEX_LOG(my_idx);
 
-       /*
-        *  The scsi layer should be handling this stuff
-        *  (In 2.3.x it does -DaveM)
-        */
-
-       /*  BUG FIX!  19991030 -sralston
-        *    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
+       /*    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
         *    Seems we may receive a buffer (datalen>0) even when there
         *    will be no data transfer!  GRRRRR...
         */
-       datadir = mptscsih_io_direction(SCpnt);
-       if (datadir == SCSI_DATA_READ) {
+       if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
                datalen = SCpnt->request_bufflen;
                scsidir = MPI_SCSIIO_CONTROL_READ;      /* DATA IN  (host<--ioc<--dev) */
-       } else if (datadir == SCSI_DATA_WRITE) {
+       } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
                datalen = SCpnt->request_bufflen;
                scsidir = MPI_SCSIIO_CONTROL_WRITE;     /* DATA OUT (host-->ioc-->dev) */
        } else {
@@ -2344,8 +1358,8 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        /* Default to untagged. Once a target structure has been allocated,
         * use the Inquiry data to determine if device supports tagged.
         */
-       if (   pTarget
-           && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+       if (vdev
+           && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
            && (SCpnt->device->tagged_supported)) {
                scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
        } else {
@@ -2354,10 +1368,13 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 
        /* Use the above information to set up the message frame
         */
-       pScsiReq->TargetID = (u8) target;
-       pScsiReq->Bus = (u8) SCpnt->device->channel;
+       pScsiReq->TargetID = (u8) vdev->vtarget->target_id;
+       pScsiReq->Bus = vdev->vtarget->bus_id;
        pScsiReq->ChainOffset = 0;
-       pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
+       if (vdev->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)
+               pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
+       else
+               pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
        pScsiReq->CDBLength = SCpnt->cmd_len;
        pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
        pScsiReq->Reserved = 0;
@@ -2392,147 +1409,30 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        /* Now add the SG list
         * Always have a SGE even if null length.
         */
-       rc = SUCCESS;
        if (datalen == 0) {
                /* Add a NULL SGE */
                mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
                        (dma_addr_t) -1);
        } else {
                /* Add a 32 or 64 bit SGE */
-               rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
+               if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
+                       goto fail;
        }
 
+       SCpnt->host_scribble = (unsigned char *)mf;
+       hd->ScsiLookup[my_idx] = SCpnt;
 
-       if (rc == SUCCESS) {
-               hd->ScsiLookup[my_idx] = SCpnt;
-               SCpnt->host_scribble = NULL;
-
-               /* SCSI specific processing */
-               issueCmd = 1;
-               if (hd->is_spi) {
-                       int dvStatus = hd->ioc->spi_data.dvStatus[target];
-
-                       if (dvStatus || hd->ioc->spi_data.forceDv) {
-
-                               /* Write SDP1 on this I/O to this target */
-                               if (dvStatus & MPT_SCSICFG_NEGOTIATE) {
-                                       mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);
-                                       dvStatus &= ~MPT_SCSICFG_NEGOTIATE;
-                                       hd->ioc->spi_data.dvStatus[target] =  dvStatus;
-                               } else if (dvStatus & MPT_SCSICFG_BLK_NEGO) {
-                                       mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO);
-                                       dvStatus &= ~MPT_SCSICFG_BLK_NEGO;
-                                       hd->ioc->spi_data.dvStatus[target] =  dvStatus;
-                               }
-
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-                               if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
-                                       (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
-                                       unsigned long lflags;
-                                       /* Schedule DV if necessary */
-                                       spin_lock_irqsave(&dvtaskQ_lock, lflags);
-                                       if (!dvtaskQ_active) {
-                                               dvtaskQ_active = 1;
-                                               spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-                                               MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
-
-                                               SCHEDULE_TASK(&mptscsih_dvTask);
-                                       } else {
-                                               spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-                                       }
-                                       hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
-                               }
-
-                               /* Trying to do DV to this target, extend timeout.
-                                * Wait to issue intil flag is clear
-                                */
-                               if (dvStatus & MPT_SCSICFG_DV_PENDING) {
-                                       mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
-                                       issueCmd = 0;
-                               }
-
-                               /* Set the DV flags.
-                                */
-                               if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
-                                       mptscsih_set_dvflags(hd, pScsiReq);
-#endif
-                       }
-               }
-
-#ifdef MPTSCSIH_DBG_TIMEOUT
-               if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) {
-                       foo_to[hd->ioc->timeout_cnt] = SCpnt;
-                       hd->ioc->timeout_cnt++;
-                       //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta);
-                       issueCmd = 0;
-                       printk(MYIOC_s_WARN_FMT
-                               "to pendingQ: (sc=%p, mf=%p, time=%ld)\n",
-                               hd->ioc->name, SCpnt, mf, jiffies);
-               }
-#endif
-
-               if (issueCmd) {
-                       mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
-                       dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
-                                       hd->ioc->name, SCpnt, mf, my_idx));
-               } else {
-                       ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",
-                                       hd->ioc->name, SCpnt, my_idx));
-                       /* Place this command on the pendingQ if possible */
-                       spin_lock_irqsave(&hd->freedoneQlock, flags);
-                       if (!Q_IS_EMPTY(&hd->freeQ)) {
-                               buffer = hd->freeQ.head;
-                               Q_DEL_ITEM(buffer);
-
-                               /* Save the mf pointer
-                                */
-                               buffer->argp = (void *)mf;
-
-                               /* Add to the pendingQ
-                                */
-                               Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);
-                               spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-                       } else {
-                               spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-                               SCpnt->result = (DID_BUS_BUSY << 16);
-                               SCpnt->scsi_done(SCpnt);
-                       }
-               }
-       } else {
-               mptscsih_freeChainBuffers(hd, my_idx);
-               mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
-               did_errcode = 3;
-               goto did_error;
-       }
-
+       mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
+       dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
+                       hd->ioc->name, SCpnt, mf, my_idx));
+       DBG_DUMP_REQUEST_FRAME(mf)
        return 0;
 
-did_error:
-       dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n",
-                       hd->ioc->name, did_errcode, SCpnt));
-       /* Just wish OS to issue a retry */
-       SCpnt->result = (DID_BUS_BUSY << 16);
-       spin_lock_irqsave(&hd->freedoneQlock, flags);
-       if (!Q_IS_EMPTY(&hd->freeQ)) {
-               dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n",
-                       (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
-               buffer = hd->freeQ.head;
-               Q_DEL_ITEM(buffer);
-
-               /* Set the Scsi_Cmnd pointer
-                */
-               buffer->argp = (void *)SCpnt;
-
-               /* Add to the doneQ
-                */
-               Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
-               spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-       } else {
-               spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-               SCpnt->scsi_done(SCpnt);
-       }
-
-       return 0;
+ fail:
+       hd->ScsiLookup[my_idx] = NULL;
+       mptscsih_freeChainBuffers(hd->ioc, my_idx);
+       mpt_free_msg_frame(hd->ioc, mf);
+       return SCSI_MLQUEUE_HOST_BUSY;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2546,7 +1446,7 @@ did_error:
  *     No return.
  */
 static void
-mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
+mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
 {
        MPT_FRAME_HDR *chain;
        unsigned long flags;
@@ -2556,28 +1456,28 @@ mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
        /* Get the first chain index and reset
         * tracker state.
         */
-       chain_idx = hd->ReqToChain[req_idx];
-       hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
+       chain_idx = ioc->ReqToChain[req_idx];
+       ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
 
        while (chain_idx != MPT_HOST_NO_CHAIN) {
 
                /* Save the next chain buffer index */
-               next = hd->ChainToChain[chain_idx];
+               next = ioc->ChainToChain[chain_idx];
 
                /* Free this chain buffer and reset
                 * tracker
                 */
-               hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
+               ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
 
-               chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
-                                       + (chain_idx * hd->ioc->req_sz));
-               spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-               Q_ADD_TAIL(&hd->FreeChainQ.head,
-                                       &chain->u.frame.linkage, MPT_FRAME_HDR);
-               spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+               chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
+                                       + (chain_idx * ioc->req_sz));
+
+               spin_lock_irqsave(&ioc->FreeQlock, flags);
+               list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
+               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
                dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
-                               hd->ioc->name, chain_idx));
+                               ioc->name, chain_idx));
 
                /* handle next */
                chain_idx = next;
@@ -2601,7 +1501,6 @@ mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
  *     @target: Logical Target ID for reset (if appropriate)
  *     @lun: Logical Unit for reset (if appropriate)
  *     @ctx2abort: Context for the task to be aborted (if appropriate)
- *     @sleepFlag: If set, use udelay instead of schedule in handshake code.
  *
  *     Remark: Currently invoked from a non-interrupt thread (_bh).
  *
@@ -2610,8 +1509,8 @@ mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
  *
  *     Returns 0 for SUCCESS or -1 if FAILED.
  */
-static int
-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
+int
+mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
 {
        MPT_ADAPTER     *ioc;
        int              rc = -1;
@@ -2641,12 +1540,6 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
        }
        spin_unlock_irqrestore(&ioc->diagLock, flags);
 
-       /* Do not do a Task Management if there are
-        * too many failed TMs on this adapter.
-        */
-       if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM)
-               doTask = 0;
-
        /*  Wait a fixed amount of time for the TM pending flag to be cleared.
         *  If we time out and not bus reset, then we return a FAILED status to the caller.
         *  The call to mptscsih_tm_pending_wait() will set the pending flag if we are
@@ -2654,17 +1547,17 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
         */
        if (mptscsih_tm_pending_wait(hd) == FAILED) {
                if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
-                       dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
+                       dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
                           "Timed out waiting for last TM (%d) to complete! \n",
                           hd->ioc->name, hd->tmPending));
                        return FAILED;
                } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
-                       dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
+                       dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
                           "Timed out waiting for last TM (%d) to complete! \n",
                           hd->ioc->name, hd->tmPending));
                        return FAILED;
                } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
-                       dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
+                       dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
                           "Timed out waiting for last TM (%d) to complete! \n",
                           hd->ioc->name, hd->tmPending));
                        if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
@@ -2697,7 +1590,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
                 */
                if (hd->hard_resets < -1)
                        hd->hard_resets++;
-               rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag);
+               rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
                if (rc) {
                        printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
                } else {
@@ -2705,20 +1598,21 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
                }
        }
 
-#ifdef MPTSCSIH_DBG_TIMEOUT
-       if (hd->ioc->timeout_hard)
-               rc = 1;
-#endif
-
        /* Only fall through to the HRH if this is a bus reset
         */
        if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
                ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
                dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
                         hd->ioc->name));
-               rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
+               rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
        }
 
+       /*
+        * Check IOCStatus from TM reply message
+        */
+        if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
+               rc = FAILED;
+
        dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
 
        return rc;
@@ -2733,7 +1627,6 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
  *     @target: Logical Target ID for reset (if appropriate)
  *     @lun: Logical Unit for reset (if appropriate)
  *     @ctx2abort: Context for the task to be aborted (if appropriate)
- *     @sleepFlag: If set, use udelay instead of schedule in handshake code.
  *
  *     Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
  *     or a non-interrupt thread.  In the former, must not call schedule().
@@ -2744,7 +1637,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
  *     else other non-zero value returned.
  */
 static int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
 {
        MPT_FRAME_HDR   *mf;
        SCSITaskMgmt_t  *pScsiTm;
@@ -2753,11 +1646,10 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
 
        /* Return Fail to calling function if no message frames available.
         */
-       if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
-               dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
+       if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
+               dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
                                hd->ioc->name));
-               //return FAILED;
-               return -999;
+               return FAILED;
        }
        dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
                        hd->ioc->name, mf));
@@ -2774,7 +1666,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
        pScsiTm->TaskType = type;
        pScsiTm->Reserved1 = 0;
        pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
-                           ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
+                    ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
 
        for (ii= 0; ii < 8; ii++) {
                pScsiTm->LUN[ii] = 0;
@@ -2785,97 +1677,104 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
                pScsiTm->Reserved2[ii] = 0;
 
        pScsiTm->TaskMsgContext = ctx2abort;
-       dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n",
+
+       dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
                        hd->ioc->name, ctx2abort, type));
 
-       /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
-               mpt_put_msg_frame(hd->ioc->id, mf);
-       * Save the MF pointer in case the request times out.
-       */
-       hd->tmPtr = mf;
-       hd->numTMrequests++;
-       hd->TMtimer.expires = jiffies + timeout;
-       add_timer(&hd->TMtimer);
-
-       if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
-                               sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
-       != 0) {
-               dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
-                       " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
-               hd->numTMrequests--;
-               hd->tmPtr = NULL;
-               del_timer(&hd->TMtimer);
-               mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
+       DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
+
+       if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
+               sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
+               CAN_SLEEP)) != 0) {
+               dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
+                       " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+                       hd->ioc, mf));
+               mpt_free_msg_frame(hd->ioc, mf);
+               return retval;
+       }
+
+       if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
+               dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
+                       " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+                       hd->ioc, mf));
+               mpt_free_msg_frame(hd->ioc, mf);
+               dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
+                        hd->ioc->name));
+               retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
        }
 
        return retval;
 }
 
+static int
+mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
+{
+       switch (ioc->bus_type) {
+       case FC:
+               return 40;
+       case SAS:
+               return 10;
+       case SPI:
+       default:
+               return 2;
+       }
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
- *     @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
+ *     mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
+ *     @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
  *
- *     (linux Scsi_Host_Template.eh_abort_handler routine)
+ *     (linux scsi_host_template.eh_abort_handler routine)
  *
  *     Returns SUCCESS or FAILED.
  */
 int
-mptscsih_abort(Scsi_Cmnd * SCpnt)
+mptscsih_abort(struct scsi_cmnd * SCpnt)
 {
        MPT_SCSI_HOST   *hd;
        MPT_FRAME_HDR   *mf;
        u32              ctx2abort;
        int              scpnt_idx;
-       spinlock_t      *host_lock = SCpnt->device->host->host_lock;
+       int              retval;
+       VirtDevice       *vdev;
+       ulong            sn = SCpnt->serial_number;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
        if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
                SCpnt->result = DID_RESET << 16;
                SCpnt->scsi_done(SCpnt);
-               dtmprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
+               dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
                           "Can't locate host! (sc=%p)\n",
                           SCpnt));
                return FAILED;
        }
 
-       if (hd->resetPending)
-               return FAILED;
-
-       printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
-              hd->ioc->name, SCpnt);
-
-       if (hd->timeouts < -1)
-               hd->timeouts++;
-
        /* Find this command
         */
        if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
-               /* Cmd not found in ScsiLookup. If found in
-                * doneQ, delete from Q. Do OS callback.
+               /* Cmd not found in ScsiLookup.
+                * Do OS callback.
                 */
-               search_doneQ_for_cmd(hd, SCpnt);
-
                SCpnt->result = DID_RESET << 16;
-               dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
+               dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
                           "Command not in the active list! (sc=%p)\n",
                           hd->ioc->name, SCpnt));
                return SUCCESS;
        }
 
-       /* If this command is pended, then timeout/hang occurred
-        * during DV. Post command and flush pending Q
-        * and then following up with the reset request.
-        */
-       if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
-               mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
-               post_pendingQ_commands(hd);
-               dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
-                          "Posting pended cmd! (sc=%p)\n",
-                          hd->ioc->name, SCpnt));
+       if (hd->resetPending) {
+               return FAILED;
        }
 
+       if (hd->timeouts < -1)
+               hd->timeouts++;
+
+       printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
+              hd->ioc->name, SCpnt);
+       scsi_print_command(SCpnt);
+
        /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
         * (the IO to be ABORT'd)
         *
@@ -2888,50 +1787,50 @@ mptscsih_abort(Scsi_Cmnd * SCpnt)
 
        hd->abortSCpnt = SCpnt;
 
-       spin_unlock_irq(host_lock);
-       if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-               SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
-               ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP)
-               < 0) {
+       vdev = SCpnt->device->hostdata;
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
+               vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
+               ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
 
-               /* The TM request failed and the subsequent FW-reload failed!
-                * Fatal error case.
-                */
-               printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
-                      hd->ioc->name, SCpnt);
+       if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
+           SCpnt->serial_number == sn) {
+               retval = FAILED;
+       }
 
-               /* We must clear our pending flag before clearing our state.
-                */
+       printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
+               hd->ioc->name,
+               ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+
+       if (retval == 0)
+               return SUCCESS;
+
+       if(retval != FAILED ) {
                hd->tmPending = 0;
                hd->tmState = TM_STATE_NONE;
-
-               spin_lock_irq(host_lock);
-               return FAILED;
        }
-       spin_lock_irq(host_lock);
        return FAILED;
-
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant
- *     @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ *     @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
  *
- *     (linux Scsi_Host_Template.eh_dev_reset_handler routine)
+ *     (linux scsi_host_template.eh_dev_reset_handler routine)
  *
  *     Returns SUCCESS or FAILED.
  */
 int
-mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
+mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 {
        MPT_SCSI_HOST   *hd;
-       spinlock_t      *host_lock = SCpnt->device->host->host_lock;
+       int              retval;
+       VirtDevice       *vdev;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
        if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-               dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
+               dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
                           "Can't locate host! (sc=%p)\n",
                           SCpnt));
                return FAILED;
@@ -2940,120 +1839,108 @@ mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
        if (hd->resetPending)
                return FAILED;
 
-       printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
+       printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
               hd->ioc->name, SCpnt);
+       scsi_print_command(SCpnt);
 
-       /* Unsupported for SCSI. Supported for FCP
-        */
-       if (hd->is_spi)
-               return FAILED;
+       vdev = SCpnt->device->hostdata;
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+               vdev->vtarget->bus_id, vdev->vtarget->target_id,
+               0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
-       spin_unlock_irq(host_lock);
-       if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-               SCpnt->device->channel, SCpnt->device->id,
-               0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
-               < 0){
-               /* The TM request failed and the subsequent FW-reload failed!
-                * Fatal error case.
-                */
-               printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
-                               hd->ioc->name, SCpnt);
+       printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
+               hd->ioc->name,
+               ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+
+       if (retval == 0)
+               return SUCCESS;
+
+       if(retval != FAILED ) {
                hd->tmPending = 0;
                hd->tmState = TM_STATE_NONE;
-               spin_lock_irq(host_lock);
-               return FAILED;
        }
-       spin_lock_irq(host_lock);
-       return SUCCESS;
-
+       return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_bus_reset - Perform a SCSI BUS_RESET!  new_eh variant
- *     @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ *     @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
  *
- *     (linux Scsi_Host_Template.eh_bus_reset_handler routine)
+ *     (linux scsi_host_template.eh_bus_reset_handler routine)
  *
  *     Returns SUCCESS or FAILED.
  */
 int
-mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
+mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
        MPT_SCSI_HOST   *hd;
-       spinlock_t      *host_lock = SCpnt->device->host->host_lock;
+       int              retval;
+       VirtDevice       *vdev;
 
        /* If we can't locate our host adapter structure, return FAILED status.
         */
        if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-               dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
+               dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
                           "Can't locate host! (sc=%p)\n",
                           SCpnt ) );
                return FAILED;
        }
 
-       printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
+       printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
               hd->ioc->name, SCpnt);
+       scsi_print_command(SCpnt);
 
        if (hd->timeouts < -1)
                hd->timeouts++;
 
-       /* We are now ready to execute the task management request. */
-       spin_unlock_irq(host_lock);
-//     printk("testing start : mptscsih_schedule_reset\n");
-//     mptscsih_schedule_reset(hd);
-//     printk("testing end: mptscsih_schedule_reset\n");
-       if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-               SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
-           < 0){
-
-               /* The TM request failed and the subsequent FW-reload failed!
-                * Fatal error case.
-                */
-               printk(MYIOC_s_WARN_FMT
-                      "Error processing TaskMgmt request (sc=%p)\n",
-                      hd->ioc->name, SCpnt);
+       vdev = SCpnt->device->hostdata;
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+               vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
+
+       printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
+               hd->ioc->name,
+               ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+
+       if (retval == 0)
+               return SUCCESS;
+
+       if(retval != FAILED ) {
                hd->tmPending = 0;
                hd->tmState = TM_STATE_NONE;
-               spin_lock_irq(host_lock);
-               return FAILED;
        }
-       spin_lock_irq(host_lock);
-       return SUCCESS;
+       return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mptscsih_host_reset - Perform a SCSI host adapter RESET!
- *     new_eh variant
- *     @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
+ *     mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
+ *     @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
  *
- *     (linux Scsi_Host_Template.eh_host_reset_handler routine)
+ *     (linux scsi_host_template.eh_host_reset_handler routine)
  *
  *     Returns SUCCESS or FAILED.
  */
 int
-mptscsih_host_reset(Scsi_Cmnd *SCpnt)
+mptscsih_host_reset(struct scsi_cmnd *SCpnt)
 {
        MPT_SCSI_HOST *  hd;
        int              status = SUCCESS;
-       spinlock_t      *host_lock = SCpnt->device->host->host_lock;
 
        /*  If we can't locate the host to reset, then we failed. */
        if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
-               dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+               dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
                             "Can't locate host! (sc=%p)\n",
                             SCpnt ) );
                return FAILED;
        }
 
-       printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
+       printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
               hd->ioc->name, SCpnt);
 
        /*  If our attempts to reset the host failed, then return a failed
         *  status.  The host will be taken off line by the SCSI mid-layer.
         */
-       spin_unlock_irq(host_lock);
        if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
                status = FAILED;
        } else {
@@ -3063,10 +1950,8 @@ mptscsih_host_reset(Scsi_Cmnd *SCpnt)
                hd->tmPending = 0;
                hd->tmState = TM_STATE_NONE;
        }
-       spin_lock_irq(host_lock);
-
 
-       dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+       dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
                     "Status = %s\n",
                     (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
 
@@ -3075,8 +1960,7 @@ mptscsih_host_reset(Scsi_Cmnd *SCpnt)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *     mptscsih_tm_pending_wait - wait for pending task management request to
- *             complete.
+ *     mptscsih_tm_pending_wait - wait for pending task management request to complete
  *     @hd: Pointer to MPT host structure.
  *
  *     Returns {SUCCESS,FAILED}.
@@ -3085,7 +1969,7 @@ static int
 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
 {
        unsigned long  flags;
-       int            loop_count = 10 * 4;  /* Wait 10 seconds */
+       int            loop_count = 4 * 10;  /* Wait 10 seconds */
        int            status = FAILED;
 
        do {
@@ -3098,13 +1982,77 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
                        break;
                }
                spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(HZ/4);
+               msleep(250);
+       } while (--loop_count);
+
+       return status;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *     mptscsih_tm_wait_for_completion - wait for completion of TM task
+ *     @hd: Pointer to MPT host structure.
+ *     @timeout: timeout in seconds
+ *
+ *     Returns {SUCCESS,FAILED}.
+ */
+static int
+mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
+{
+       unsigned long  flags;
+       int            loop_count = 4 * timeout;
+       int            status = FAILED;
+
+       do {
+               spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+               if(hd->tmPending == 0) {
+                       status = SUCCESS;
+                       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+                       break;
+               }
+               spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+               msleep(250);
        } while (--loop_count);
 
        return status;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static void
+mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
+{
+       char *desc;
+
+       switch (response_code) {
+       case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
+               desc = "The task completed.";
+               break;
+       case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
+               desc = "The IOC received an invalid frame status.";
+               break;
+       case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
+               desc = "The task type is not supported.";
+               break;
+       case MPI_SCSITASKMGMT_RSP_TM_FAILED:
+               desc = "The requested task failed.";
+               break;
+       case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
+               desc = "The task completed successfully.";
+               break;
+       case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
+               desc = "The LUN request is invalid.";
+               break;
+       case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
+               desc = "The task is in the IOC queue and has not been sent to target.";
+               break;
+       default:
+               desc = "unknown";
+               break;
+       }
+       printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
+               ioc->name, response_code, desc);
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
@@ -3119,16 +2067,17 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
  *
  *     Returns 1 indicating alloc'd request frame ptr should be freed.
  */
-static int
+int
 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 {
        SCSITaskMgmtReply_t     *pScsiTmReply;
        SCSITaskMgmt_t          *pScsiTmReq;
        MPT_SCSI_HOST           *hd;
        unsigned long            flags;
-       u8                       tmType = 0;
+       u16                      iocstatus;
+       u8                       tmType;
 
-       dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
+       dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
                        ioc->name, mf, mr));
        if (ioc->sh) {
                /* Depending on the thread, a timer is activated for
@@ -3136,11 +2085,6 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
                 * Decrement count of outstanding TM requests.
                 */
                hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
-               if (hd->tmPtr) {
-                       del_timer(&hd->TMtimer);
-               }
-               dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
-                       ioc->name, hd->taskQcnt));
        } else {
                dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
                        ioc->name));
@@ -3158,18 +2102,21 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
                /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
                tmType = pScsiTmReq->TaskType;
 
-               dtmprintk((KERN_INFO "  TaskType = %d, TerminationCount=%d\n",
-                               tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
+               if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
+                   pScsiTmReply->ResponseCode)
+                       mptscsih_taskmgmt_response_code(ioc,
+                           pScsiTmReply->ResponseCode);
 
-               /* Error?  (anything non-zero?) */
-               if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
-                       u16      iocstatus;
+               dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
+                               ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
+               DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
 
-                       iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-                       dtmprintk((KERN_INFO "  SCSI TaskMgmt (%d) - Oops!\n", tmType));
-                       dtmprintk((KERN_INFO "  IOCStatus = %04xh\n", iocstatus));
-                       dtmprintk((KERN_INFO "  IOCLogInfo = %08xh\n",
-                                le32_to_cpu(pScsiTmReply->IOCLogInfo)));
+               iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+               hd->tm_iocstatus = iocstatus;
+               dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
+                       ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
+               /* Error?  (anything non-zero?) */
+               if (iocstatus) {
 
                        /* clear flags and continue.
                         */
@@ -3190,16 +2137,13 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
                                }
                        }
                } else {
-                       dtmprintk((KERN_INFO "  SCSI TaskMgmt SUCCESS!\n"));
+                       dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
 
-                       hd->numTMrequests--;
                        hd->abortSCpnt = NULL;
-                       flush_doneQ(hd);
 
                }
        }
 
-       hd->tmPtr = NULL;
        spin_lock_irqsave(&ioc->FreeQlock, flags);
        hd->tmPending = 0;
        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
@@ -3219,19 +2163,14 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
        int             heads;
        int             sectors;
        sector_t        cylinders;
-#ifdef CONFIG_LBD
        ulong           dummy;
-#endif
 
        heads = 64;
        sectors = 32;
-#ifdef CONFIG_LBD
+
        dummy = heads * sectors;
        cylinders = capacity;
        sector_div(cylinders,dummy);
-#else
-       cylinders = (ulong)capacity / (heads * sectors);
-#endif
 
        /*
         * Handle extended translation size for logical drives
@@ -3240,13 +2179,9 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
        if ((ulong)capacity >= 0x200000) {
                heads = 255;
                sectors = 63;
-#ifdef CONFIG_LBD
                dummy = heads * sectors;
                cylinders = capacity;
                sector_div(cylinders,dummy);
-#else
-               cylinders = (ulong)capacity / (heads * sectors);
-#endif
        }
 
        /* return result */
@@ -3261,110 +2196,188 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
        return 0;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     OS entry point to allow host driver to alloc memory
- *     for each scsi device. Called once per device the bus scan.
- *     Return non-zero if allocation fails.
- *     Init memory once per id (not LUN).
+/* Search IOC page 3 to determine if this is hidden physical disk
+ *
  */
 int
-mptscsih_slave_alloc(Scsi_Device *device)
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
 {
-       struct Scsi_Host        *host = device->host;
-       MPT_SCSI_HOST           *hd;
-       VirtDevice              *vdev;
+       int i;
 
-       hd = (MPT_SCSI_HOST *)host->hostdata;
+       if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
+               return 0;
+       for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+                if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+                        return 1;
+        }
+        return 0;
+}
+EXPORT_SYMBOL(mptscsih_is_phys_disk);
 
-       if (hd == NULL)
-               return -ENODEV;
+int
+mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid)
+{
+       int i;
 
-       if ((vdev = hd->Targets[device->id]) == NULL) {
-               if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
-                       printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%d) FAILED!\n",
-                       hd->ioc->name, (int)sizeof(VirtDevice));
-                       return -ENOMEM;
-               } else {
-                       memset(vdev, 0, sizeof(VirtDevice));
-                       rwlock_init(&vdev->VdevLock);
-                       Q_INIT(&vdev->WaitQ, void);
-                       Q_INIT(&vdev->SentQ, void);
-                       Q_INIT(&vdev->DoneQ, void);
-                       vdev->tflags = 0;
-                       vdev->ioc_id = hd->ioc->id;
-                       vdev->target_id = device->id;
-                       vdev->bus_id = hd->port;
-
-                       hd->Targets[device->id] = vdev;
-               }
+       if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)
+               return -ENXIO;
+
+       for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+               if (physdiskid ==
+                   hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+                       return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
        }
-       vdev->num_luns++;
 
+       return -ENXIO;
+}
+EXPORT_SYMBOL(mptscsih_raid_id_to_num);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     OS entry point to allow host driver to alloc memory
+ *     for each scsi target. Called once per device the bus scan.
+ *     Return non-zero if allocation fails.
+ */
+int
+mptscsih_target_alloc(struct scsi_target *starget)
+{
+       VirtTarget              *vtarget;
+
+       vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+       if (!vtarget)
+               return -ENOMEM;
+       starget->hostdata = vtarget;
+       vtarget->starget = starget;
        return 0;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     OS entry point to allow for host driver to free allocated memory
- *     Called if no device present or device being unloaded
+ *     OS entry point to allow host driver to alloc memory
+ *     for each scsi device. Called once per device the bus scan.
+ *     Return non-zero if allocation fails.
  */
-void
-mptscsih_slave_destroy(Scsi_Device *device)
+int
+mptscsih_slave_alloc(struct scsi_device *sdev)
 {
-       struct Scsi_Host        *host = device->host;
-       MPT_SCSI_HOST           *hd;
+       struct Scsi_Host        *host = sdev->host;
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       VirtTarget              *vtarget;
        VirtDevice              *vdev;
-       int                     raid_volume=0;
+       struct scsi_target      *starget;
 
-       hd = (MPT_SCSI_HOST *)host->hostdata;
+       vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
+       if (!vdev) {
+               printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+                               hd->ioc->name, sizeof(VirtDevice));
+               return -ENOMEM;
+       }
 
-       if (hd == NULL)
-               return;
+       vdev->lun = sdev->lun;
+       sdev->hostdata = vdev;
 
-       mptscsih_search_running_cmds(hd, device->id, device->lun);
+       starget = scsi_target(sdev);
+       vtarget = starget->hostdata;
 
-       /* Free memory and reset all flags for this target
-        */
-       if ((vdev = hd->Targets[device->id]) != NULL) {
-               vdev->num_luns--;
+       vdev->vtarget = vtarget;
 
-               if (vdev->luns[0] & (1 << device->lun))
-                       vdev->luns[0] &= ~(1 << device->lun);
+       if (vtarget->num_luns == 0) {
+               hd->Targets[sdev->id] = vtarget;
+               vtarget->ioc_id = hd->ioc->id;
+               vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+               vtarget->target_id = sdev->id;
+               vtarget->bus_id = sdev->channel;
+               if (hd->ioc->bus_type == SPI && sdev->channel == 0 &&
+                   hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
+                       vtarget->raidVolume = 1;
+                       ddvtprintk((KERN_INFO
+                                   "RAID Volume @ id %d\n", sdev->id));
+               }
+       }
+       vtarget->num_luns++;
+       return 0;
+}
 
-               /* Free device structure only if number of luns is 0.
-                */
-               if (vdev->num_luns == 0) {
-                       kfree(hd->Targets[device->id]);
-                       hd->Targets[device->id] = NULL;
-
-                       if (!hd->is_spi) 
-                               return;
-
-                       if((hd->ioc->spi_data.isRaid) && (hd->ioc->spi_data.pIocPg3)) {
-                       int i;
-                               for(i=0;i<hd->ioc->spi_data.pIocPg3->NumPhysDisks &&
-                                       raid_volume==0;i++)
-                                               
-                                       if(device->id == 
-                                         hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) {
-                                               raid_volume=1;
-                                               hd->ioc->spi_data.forceDv |=
-                                                 MPT_SCSICFG_RELOAD_IOC_PG3;
-                                       }
-                       }
+/*
+ *     OS entry point to allow for host driver to free allocated memory
+ *     Called if no device present or device being unloaded
+ */
+void
+mptscsih_target_destroy(struct scsi_target *starget)
+{
+       if (starget->hostdata)
+               kfree(starget->hostdata);
+       starget->hostdata = NULL;
+}
+
+/*
+ *     OS entry point to allow for host driver to free allocated memory
+ *     Called if no device present or device being unloaded
+ */
+void
+mptscsih_slave_destroy(struct scsi_device *sdev)
+{
+       struct Scsi_Host        *host = sdev->host;
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       VirtTarget              *vtarget;
+       VirtDevice              *vdevice;
+       struct scsi_target      *starget;
 
-                       if(!raid_volume){
-                               hd->ioc->spi_data.dvStatus[device->id] =
-                               MPT_SCSICFG_NEGOTIATE;
+       starget = scsi_target(sdev);
+       vtarget = starget->hostdata;
+       vdevice = sdev->hostdata;
 
-                               if (hd->negoNvram == 0)
-                                       hd->ioc->spi_data.dvStatus[device->id]
-                                       |= MPT_SCSICFG_DV_NOT_DONE;
-                       }
-               }
+       mptscsih_search_running_cmds(hd, vdevice);
+       vtarget->luns[0] &= ~(1 << vdevice->lun);
+       vtarget->num_luns--;
+       if (vtarget->num_luns == 0) {
+               hd->Targets[sdev->id] = NULL;
        }
-       
-       return;
+       mptscsih_synchronize_cache(hd, vdevice);
+       kfree(vdevice);
+       sdev->hostdata = NULL;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     mptscsih_change_queue_depth - This function will set a devices queue depth
+ *     @sdev: per scsi_device pointer
+ *     @qdepth: requested queue depth
+ *
+ *     Adding support for new 'change_queue_depth' api.
+*/
+int
+mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+       VirtTarget              *vtarget;
+       struct scsi_target      *starget;
+       int                     max_depth;
+       int                     tagged;
+
+       starget = scsi_target(sdev);
+       vtarget = starget->hostdata;
+
+       if (hd->ioc->bus_type == SPI) {
+               if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+                       max_depth = 1;
+               else if (sdev->type == TYPE_DISK &&
+                        vtarget->minSyncFactor <= MPT_ULTRA160)
+                       max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+               else
+                       max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
+       } else
+               max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+
+       if (qdepth > max_depth)
+               qdepth = max_depth;
+       if (qdepth == 1)
+               tagged = 0;
+       else
+               tagged = MSG_SIMPLE_TAG;
+
+       scsi_adjust_queue_depth(sdev, tagged, qdepth);
+       return sdev->queue_depth;
 }
 
 /*
@@ -3374,78 +2387,61 @@ mptscsih_slave_destroy(Scsi_Device *device)
  *     Return non-zero if fails.
  */
 int
-mptscsih_slave_configure(Scsi_Device *device)
+mptscsih_slave_configure(struct scsi_device *sdev)
 {
-       struct Scsi_Host        *sh = device->host;
-       VirtDevice              *pTarget;
+       struct Scsi_Host        *sh = sdev->host;
+       VirtTarget              *vtarget;
+       VirtDevice              *vdevice;
+       struct scsi_target      *starget;
        MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sh->hostdata;
+       int                     indexed_lun, lun_index;
 
-       if ((hd == NULL) || (hd->Targets == NULL)) {
-               return 0;
-       }
+       starget = scsi_target(sdev);
+       vtarget = starget->hostdata;
+       vdevice = sdev->hostdata;
 
        dsprintk((MYIOC_s_INFO_FMT
                "device @ %p, id=%d, LUN=%d, channel=%d\n",
-               hd->ioc->name, device, device->id, device->lun, device->channel));
-       dsprintk((MYIOC_s_INFO_FMT
-               "sdtr %d wdtr %d ppr %d inq length=%d\n",
-               hd->ioc->name, device->sdtr, device->wdtr,
-               device->ppr, device->inquiry_len));
-
-       if (device->id > sh->max_id) {
+               hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
+       if (hd->ioc->bus_type == SPI)
+               dsprintk((MYIOC_s_INFO_FMT
+                   "sdtr %d wdtr %d ppr %d inq length=%d\n",
+                   hd->ioc->name, sdev->sdtr, sdev->wdtr,
+                   sdev->ppr, sdev->inquiry_len));
+
+       if (sdev->id > sh->max_id) {
                /* error case, should never happen */
-               scsi_adjust_queue_depth(device, 0, 1);
-               goto slave_configure_exit;
-       }
-
-       pTarget = hd->Targets[device->id];
-
-       if (pTarget == NULL) {
-               /* error case - don't know about this device */
-               scsi_adjust_queue_depth(device, 0, 1);
+               scsi_adjust_queue_depth(sdev, 0, 1);
                goto slave_configure_exit;
        }
 
-       mptscsih_initTarget(hd, device->channel, device->id, device->lun,
-               device->inquiry, device->inquiry_len );
-       scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
-               MPT_SCSI_CMD_PER_DEV_HIGH);
-       if ( hd->is_spi ) {
-               if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-                       if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
-                               scsi_adjust_queue_depth(device, 0, 1);
-                       else if (((pTarget->inq_data[0] & 0x1f) == 0x00)
-                         && (pTarget->minSyncFactor <= MPT_ULTRA160 ))
-                               scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
-                                       MPT_SCSI_CMD_PER_DEV_HIGH);
-                       else
-                               scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
-                                       MPT_SCSI_CMD_PER_DEV_LOW);
-               } else {
-                       /* error case - No Inq. Data */
-                       scsi_adjust_queue_depth(device, 0, 1);
-               }
-       }
+       vdevice->configured_lun=1;
+       lun_index = (vdevice->lun >> 5);  /* 32 luns per lun_index */
+       indexed_lun = (vdevice->lun % 32);
+       vtarget->luns[lun_index] |= (1 << indexed_lun);
+       mptscsih_initTarget(hd, vtarget, sdev);
+       mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 
        dsprintk((MYIOC_s_INFO_FMT
                "Queue depth=%d, tflags=%x\n",
-               hd->ioc->name, device->queue_depth, pTarget->tflags));
+               hd->ioc->name, sdev->queue_depth, vtarget->tflags));
 
-       dsprintk((MYIOC_s_INFO_FMT
-               "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
-               hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
+       if (hd->ioc->bus_type == SPI)
+               dsprintk((MYIOC_s_INFO_FMT
+                   "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
+                   hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
+                   vtarget->minSyncFactor));
 
 slave_configure_exit:
 
        dsprintk((MYIOC_s_INFO_FMT
                "tagged %d, simple %d, ordered %d\n",
-               hd->ioc->name,device->tagged_supported, device->simple_tags,
-               device->ordered_tags));
+               hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
+               sdev->ordered_tags));
 
        return 0;
 }
 
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  Private routines...
@@ -3457,22 +2453,16 @@ slave_configure_exit:
  *
  */
 static void
-copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
+mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
 {
-       VirtDevice      *target;
+       VirtDevice      *vdev;
        SCSIIORequest_t *pReq;
        u32              sense_count = le32_to_cpu(pScsiReply->SenseCount);
-       int              index;
-       char             devFoo[96];
-       IO_Info_t        thisIo;
 
        /* Get target structure
         */
        pReq = (SCSIIORequest_t *) mf;
-       index = (int) pReq->TargetID;
-       target = hd->Targets[index];
-       if (hd->is_multipath && sc->device->hostdata)
-               target = (VirtDevice *) sc->device->hostdata;
+       vdev = sc->device->hostdata;
 
        if (sense_count) {
                u8 *sense_data;
@@ -3486,56 +2476,38 @@ copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply
                /* Log SMART data (asc = 0x5D, non-IM case only) if required.
                 */
                if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
-                       if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
+                       if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
                                int idx;
                                MPT_ADAPTER *ioc = hd->ioc;
 
-                               idx = ioc->eventContext % ioc->eventLogSize;
+                               idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
                                ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
                                ioc->events[idx].eventContext = ioc->eventContext;
 
                                ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
                                        (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
-                                       (pReq->Bus << 8) || pReq->TargetID;
+                                       (sc->device->channel << 8) || sc->device->id;
 
                                ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
 
                                ioc->eventContext++;
+                               if (hd->ioc->pcidev->vendor ==
+                                   PCI_VENDOR_ID_IBM) {
+                                       mptscsih_issue_sep_command(hd->ioc,
+                                           vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
+                                       vdev->vtarget->tflags |=
+                                           MPT_TARGET_FLAGS_LED_ON;
+                               }
                        }
                }
-
-               /* Print an error report for the user.
-                */
-               thisIo.cdbPtr = sc->cmnd;
-               thisIo.sensePtr = sc->sense_buffer;
-               thisIo.SCSIStatus = pScsiReply->SCSIStatus;
-               thisIo.DoDisplay = 1;
-               if (hd->is_multipath)
-                       sprintf(devFoo, "%d:%d:%d",
-                                       hd->ioc->id,
-                                       pReq->TargetID,
-                                       pReq->LUN[1]);
-               else
-                       sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->device->id, sc->device->lun);
-               thisIo.DevIDStr = devFoo;
-/* fubar */
-               thisIo.dataPtr = NULL;
-               thisIo.inqPtr = NULL;
-               if (sc->device) {
-                       thisIo.inqPtr = sc->device->vendor-8;   /* FIXME!!! */
-               }
-               (void) mpt_ScsiHost_ErrorReport(&thisIo);
-
        } else {
                dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
                                hd->ioc->name));
        }
-
-       return;
 }
 
-static u32
-SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
+static int
+SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
 {
        MPT_SCSI_HOST *hd;
        int i;
@@ -3551,108 +2523,13 @@ SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
        return -1;
 }
 
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Search the pendingQ for a command with specific index.
- * If found, delete and return mf pointer
- * If not found, return NULL
- */
-static MPT_FRAME_HDR *
-mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx)
-{
-       unsigned long    flags;
-       MPT_DONE_Q      *buffer;
-       MPT_FRAME_HDR   *mf = NULL;
-       MPT_FRAME_HDR   *cmdMfPtr;
-
-       ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
-       cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
-       spin_lock_irqsave(&hd->freedoneQlock, flags);
-       if (!Q_IS_EMPTY(&hd->pendingQ)) {
-               buffer = hd->pendingQ.head;
-               do {
-                       mf = (MPT_FRAME_HDR *) buffer->argp;
-                       if (mf == cmdMfPtr) {
-                               Q_DEL_ITEM(buffer);
-
-                               /* clear the arg pointer
-                                */
-                               buffer->argp = NULL;
-
-                               /* Add to the freeQ
-                                */
-                               Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-                               break;
-                       }
-                       mf = NULL;
-               } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ);
-       }
-       spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-       ddvtprintk((" ...return %p\n", mf));
-       return mf;
-}
-
-/* Post all commands on the pendingQ to the FW.
- * Lock Q when deleting/adding members
- * Lock io_request_lock for OS callback.
- */
-static void
-post_pendingQ_commands(MPT_SCSI_HOST *hd)
-{
-       MPT_FRAME_HDR   *mf;
-       MPT_DONE_Q      *buffer;
-       unsigned long    flags;
-
-       /* Flush the pendingQ.
-        */
-       ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name));
-       while (1) {
-               spin_lock_irqsave(&hd->freedoneQlock, flags);
-               if (Q_IS_EMPTY(&hd->pendingQ)) {
-                       spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-                       break;
-               }
-
-               buffer = hd->pendingQ.head;
-               /* Delete from Q
-                */
-               Q_DEL_ITEM(buffer);
-
-               mf = (MPT_FRAME_HDR *) buffer->argp;
-               buffer->argp = NULL;
-
-               /* Add to the freeQ
-                */
-               Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-               spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-
-               if (!mf) {
-                       /* This should never happen */
-                       printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf);
-                       continue;
-               }
-
-               mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
-
-#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
-               {
-                       u16              req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-                       Scsi_Cmnd       *sc = hd->ScsiLookup[req_idx];
-                       printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
-                                       hd->ioc->name, sc, req_idx, mf);
-               }
-#endif
-       }
-
-       return;
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
+int
 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
        MPT_SCSI_HOST   *hd;
        unsigned long    flags;
+       int             ii;
 
        dtmprintk((KERN_WARNING MYNAM
                        ": IOC %s_reset routed to SCSI host driver!\n",
@@ -3681,14 +2558,10 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
 
                /* 2. Flush running commands
-                *      Clean drop test code - if compiled
                 *      Clean ScsiLookup (and associated memory)
                 *      AND clean mytaskQ
                 */
 
-               /* 2a. Drop Test Command.
-                */
-
                /* 2b. Reply to OS all known outstanding I/O commands.
                 */
                mptscsih_flush_running_cmds(hd);
@@ -3699,21 +2572,9 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                 */
                if (hd->cmdPtr) {
                        del_timer(&hd->timer);
-                       mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr);
-               }
-
-               /* 2d. If a task management has not completed,
-                * free resources associated with this request.
-                */
-               if (hd->tmPtr) {
-                       del_timer(&hd->TMtimer);
-                       mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr);
+                       mpt_free_msg_frame(ioc, hd->cmdPtr);
                }
 
-#ifdef MPTSCSIH_DBG_TIMEOUT
-               ioc->timeout_hard = 0;
-#endif
-
                dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
 
        } else {
@@ -3726,26 +2587,14 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
                /* ScsiLookup initialization
                 */
-               {
-                       int ii;
-                       for (ii=0; ii < hd->ioc->req_depth; ii++)
-                               hd->ScsiLookup[ii] = NULL;
-               }
+               for (ii=0; ii < hd->ioc->req_depth; ii++)
+                       hd->ScsiLookup[ii] = NULL;
 
                /* 2. Chain Buffer initialization
                 */
-               mptscsih_initChainBuffers(hd, 0);
 
-               /* 3. tmPtr clear
+               /* 4. Renegotiate to all devices, if SPI
                 */
-               if (hd->tmPtr) {
-                       hd->tmPtr = NULL;
-               }
-
-               /* 4. Renegotiate to all devices, if SCSI
-                */
-               if (hd->is_spi)
-                       mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
 
                /* 5. Enable new commands to be posted
                 */
@@ -3753,7 +2602,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                hd->tmPending = 0;
                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
                hd->resetPending = 0;
-               hd->numTMrequests = 0;
                hd->tmState = TM_STATE_NONE;
 
                /* 6. If there was an internal command,
@@ -3765,22 +2613,11 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                         */
                        hd->pLocal = &hd->localReply;
                        hd->pLocal->completion = MPT_SCANDV_DID_RESET;
-                       scandv_wait_done = 1;
-                       wake_up(&scandv_waitq);
+                       hd->scandv_wait_done = 1;
+                       wake_up(&hd->scandv_waitq);
                        hd->cmdPtr = NULL;
                }
 
-               /* 7. Flush doneQ
-                */
-               flush_doneQ(hd);
-
-               /* 8. Set flag to force DV and re-read IOC Page 3
-                */
-               if (hd->is_spi) {
-                       ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
-                       ddvtprintk(("Set reload IOC Pg3 Flag\n"));
-               }
-
                dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
 
        }
@@ -3789,37 +2626,39 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
+int
 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
        MPT_SCSI_HOST *hd;
        u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
 
-       dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
+       devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
                        ioc->name, event));
 
+       if (ioc->sh == NULL ||
+               ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+               return 1;
+
        switch (event) {
        case MPI_EVENT_UNIT_ATTENTION:                  /* 03 */
                /* FIXME! */
                break;
        case MPI_EVENT_IOC_BUS_RESET:                   /* 04 */
        case MPI_EVENT_EXT_BUS_RESET:                   /* 05 */
-               hd = NULL;
-               if (ioc->sh) {
-                       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-                       if (hd && (hd->is_spi) && (hd->soft_resets < -1))
-                               hd->soft_resets++;
-               }
+               if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
+                       hd->soft_resets++;
                break;
        case MPI_EVENT_LOGOUT:                          /* 09 */
                /* FIXME! */
                break;
 
+       case MPI_EVENT_RESCAN:                          /* 06 */
+               break;
+
                /*
                 *  CHECKME! Don't think we need to do
                 *  anything for these, but...
                 */
-       case MPI_EVENT_RESCAN:                          /* 06 */
        case MPI_EVENT_LINK_STATUS_CHANGE:              /* 07 */
        case MPI_EVENT_LOOP_STATE_CHANGE:               /* 08 */
                /*
@@ -3828,69 +2667,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                break;
 
        case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-               /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
-                * if DV disabled. Need to check for target mode.
-                */
-               hd = NULL;
-               if (ioc->sh)
-                       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-
-               if (hd && (hd->is_spi) && (hd->negoNvram == 0)) {
-                       ScsiCfgData     *pSpi;
-                       Ioc3PhysDisk_t  *pPDisk;
-                       int              numPDisk;
-                       u8               reason;
-                       u8               physDiskNum;
-
-                       reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
-                       if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
-                               /* New or replaced disk.
-                                * Set DV flag and schedule DV.
-                                */
-                               pSpi = &ioc->spi_data;
-                               physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
-                               ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
-                               if (pSpi->pIocPg3) {
-                                       pPDisk =  pSpi->pIocPg3->PhysDisk;
-                                       numPDisk =pSpi->pIocPg3->NumPhysDisks;
-
-                                       while (numPDisk) {
-                                               if (physDiskNum == pPDisk->PhysDiskNum) {
-                                                       pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
-                                                       pSpi->forceDv = MPT_SCSICFG_NEED_DV;
-                                                       ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
-                                                       break;
-                                               }
-                                               pPDisk++;
-                                               numPDisk--;
-                                       }
-
-                                       if (numPDisk == 0) {
-                                               /* The physical disk that needs DV was not found
-                                                * in the stored IOC Page 3. The driver must reload
-                                                * this page. DV routine will set the NEED_DV flag for
-                                                * all phys disks that have DV_NOT_DONE set.
-                                                */
-                                               pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
-                                               ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
-                                       }
-                               }
-                       }
-               }
-#endif
-
-#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
-               printk("Raid Event RF: ");
-               {
-                       u32 *m = (u32 *)pEvReply;
-                       int ii;
-                       int n = (int)pEvReply->MsgLength;
-                       for (ii=6; ii < n; ii++)
-                               printk(" %08x", le32_to_cpu(m[ii]));
-                       printk("\n");
-               }
-#endif
                break;
 
        case MPI_EVENT_NONE:                            /* 00 */
@@ -3907,947 +2683,206 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *  Private data...
- */
-static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* old symsense.c stuff... */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * Private data...
- * To protect ourselves against those that would pass us bogus pointers
+ *     mptscsih_initTarget - Target, LUN alloc/free functionality.
+ *     @hd: Pointer to MPT_SCSI_HOST structure
+ *     @vtarget: per target private data
+ *     @sdev: SCSI device
+ *
+ *     NOTE: It's only SAFE to call this routine if data points to
+ *     sane & valid STANDARD INQUIRY data!
+ *
+ *     Allocate and initialize memory for this target.
+ *     Save inquiry data.
+ *
  */
-static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
-    = { 0x1F, 0x00, 0x00, 0x00,
-       0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
-    = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00 };
-static u8 dummyCDB[16]
-    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static u8 dummyScsiData[16]
-    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-static char *ScsiStatusString[] = {
-       "GOOD",                                 /* 00h */
-       NULL,                                   /* 01h */
-       "CHECK CONDITION",                      /* 02h */
-       NULL,                                   /* 03h */
-       "CONDITION MET",                        /* 04h */
-       NULL,                                   /* 05h */
-       NULL,                                   /* 06h */
-       NULL,                                   /* 07h */
-       "BUSY",                                 /* 08h */
-       NULL,                                   /* 09h */
-       NULL,                                   /* 0Ah */
-       NULL,                                   /* 0Bh */
-       NULL,                                   /* 0Ch */
-       NULL,                                   /* 0Dh */
-       NULL,                                   /* 0Eh */
-       NULL,                                   /* 0Fh */
-       "INTERMEDIATE",                         /* 10h */
-       NULL,                                   /* 11h */
-       NULL,                                   /* 12h */
-       NULL,                                   /* 13h */
-       "INTERMEDIATE-CONDITION MET",           /* 14h */
-       NULL,                                   /* 15h */
-       NULL,                                   /* 16h */
-       NULL,                                   /* 17h */
-       "RESERVATION CONFLICT",                 /* 18h */
-       NULL,                                   /* 19h */
-       NULL,                                   /* 1Ah */
-       NULL,                                   /* 1Bh */
-       NULL,                                   /* 1Ch */
-       NULL,                                   /* 1Dh */
-       NULL,                                   /* 1Eh */
-       NULL,                                   /* 1Fh */
-       NULL,                                   /* 20h */
-       NULL,                                   /* 21h */
-       "COMMAND TERMINATED",                   /* 22h */
-       NULL,                                   /* 23h */
-       NULL,                                   /* 24h */
-       NULL,                                   /* 25h */
-       NULL,                                   /* 26h */
-       NULL,                                   /* 27h */
-       "TASK SET FULL",                        /* 28h */
-       NULL,                                   /* 29h */
-       NULL,                                   /* 2Ah */
-       NULL,                                   /* 2Bh */
-       NULL,                                   /* 2Ch */
-       NULL,                                   /* 2Dh */
-       NULL,                                   /* 2Eh */
-       NULL,                                   /* 2Fh */
-       "ACA ACTIVE",                           /* 30h */
-       NULL
-};
-
-static const char *ScsiCommonOpString[] = {
-       "TEST UNIT READY",                      /* 00h */
-       "REZERO UNIT (REWIND)",                 /* 01h */
-       NULL,                                   /* 02h */
-       "REQUEST_SENSE",                        /* 03h */
-       "FORMAT UNIT (MEDIUM)",                 /* 04h */
-       "READ BLOCK LIMITS",                    /* 05h */
-       NULL,                                   /* 06h */
-       "REASSIGN BLOCKS",                      /* 07h */
-       "READ(6)",                              /* 08h */
-       NULL,                                   /* 09h */
-       "WRITE(6)",                             /* 0Ah */
-       "SEEK(6)",                              /* 0Bh */
-       NULL,                                   /* 0Ch */
-       NULL,                                   /* 0Dh */
-       NULL,                                   /* 0Eh */
-       "READ REVERSE",                         /* 0Fh */
-       "WRITE_FILEMARKS",                      /* 10h */
-       "SPACE(6)",                             /* 11h */
-       "INQUIRY",                              /* 12h */
-       NULL
-};
-
-static const char *SenseKeyString[] = {
-       "NO SENSE",                             /* 0h */
-       "RECOVERED ERROR",                      /* 1h */
-       "NOT READY",                            /* 2h */
-       "MEDIUM ERROR",                         /* 3h */
-       "HARDWARE ERROR",                       /* 4h */
-       "ILLEGAL REQUEST",                      /* 5h */
-       "UNIT ATTENTION",                       /* 6h */
-       "DATA PROTECT",                         /* 7h */
-       "BLANK CHECK",                          /* 8h */
-       "VENDOR-SPECIFIC",                      /* 9h */
-       "ABORTED COPY",                         /* Ah */
-       "ABORTED COMMAND",                      /* Bh */
-       "EQUAL (obsolete)",                     /* Ch */
-       "VOLUME OVERFLOW",                      /* Dh */
-       "MISCOMPARE",                           /* Eh */
-       "RESERVED",                             /* Fh */
-       NULL
-};
-
-#define SPECIAL_ASCQ(c,q) \
-       (((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int dump_cdb(char *foo, unsigned char *cdb)
+static void
+mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
+                   struct scsi_device *sdev)
 {
-       int i, grpCode, cdbLen;
-       int l = 0;
-
-       grpCode = cdb[0] >> 5;
-       if (grpCode < 1)
-               cdbLen = 6;
-       else if (grpCode < 3)
-               cdbLen = 10;
-       else if (grpCode == 5)
-               cdbLen = 12;
-       else
-               cdbLen = 16;
-
-       for (i=0; i < cdbLen; i++)
-               l += sprintf(foo+l, " %02X", cdb[i]);
+       dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
+               hd->ioc->name, vtarget->bus_id, vtarget->target_id,
+               sdev->lun, hd));
 
-       return l;
-}
+       /* Is LUN supported? If so, upper 2 bits will be 0
+       * in first byte of inquiry data.
+       */
+       if (sdev->inq_periph_qual != 0)
+               return;
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*  Do ASC/ASCQ lookup/grindage to English readable string(s)  */
-static const char * ascq_set_strings_4max(
-               u8 ASC, u8 ASCQ,
-               const char **s1, const char **s2, const char **s3, const char **s4)
-{
-       static const char *asc_04_part1_string = "LOGICAL UNIT ";
-       static const char *asc_04_part2a_string = "NOT READY, ";
-       static const char *asc_04_part2b_string = "IS ";
-       static const char *asc_04_ascq_NN_part3_strings[] = {   /* ASC ASCQ (hex) */
-         "CAUSE NOT REPORTABLE",                               /* 04 00 */
-         "IN PROCESS OF BECOMING READY",                       /* 04 01 */
-         "INITIALIZING CMD. REQUIRED",                         /* 04 02 */
-         "MANUAL INTERVENTION REQUIRED",                       /* 04 03 */
-         /* Add        " IN PROGRESS" to all the following... */
-         "FORMAT",                                             /* 04 04 */
-         "REBUILD",                                            /* 04 05 */
-         "RECALCULATION",                                      /* 04 06 */
-         "OPERATION",                                          /* 04 07 */
-         "LONG WRITE",                                         /* 04 08 */
-         "SELF-TEST",                                          /* 04 09 */
-         NULL
-       };
-       static char *asc_04_part4_string = " IN PROGRESS";
-
-       static char *asc_29_ascq_NN_strings[] = {               /* ASC ASCQ (hex) */
-         "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED",      /* 29 00 */
-         "POWER ON OCCURRED",                                  /* 29 01 */
-         "SCSI BUS RESET OCCURRED",                            /* 29 02 */
-         "BUS DEVICE RESET FUNCTION OCCURRED",                 /* 29 03 */
-         "DEVICE INTERNAL RESET",                              /* 29 04 */
-         "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED",           /* 29 05 */
-         "TRANSCEIVER MODE CHANGED TO LVD",                    /* 29 06 */
-         NULL
-       };
-       static char *ascq_vendor_uniq = "(Vendor Unique)";
-       static char *ascq_noone = "(no matching ASC/ASCQ description found)";
-       int idx;
-
-       *s1 = *s2 = *s3 = *s4 = "";             /* set'em all to the empty "" string */
-
-       /* CHECKME! Need lock/sem?
-        *  Update and examine for isense module presense.
-        */
-       mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
-
-       if (mptscsih_ASCQ_TablePtr == NULL) {
-               /* 2nd chances... */
-               if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
-                       *s1 = asc_04_part1_string;
-                       *s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
-                       *s3 = asc_04_ascq_NN_part3_strings[ASCQ];
-                       /* check for " IN PROGRESS" ones */
-                       if (ASCQ >= 0x04)
-                               *s4 = asc_04_part4_string;
-               } else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
-                       *s1 = asc_29_ascq_NN_strings[ASCQ];
-               /*
-                *      Else { leave all *s[1-4] values pointing to the empty "" string }
-                */
-               return *s1;
-       }
+       if (vtarget == NULL)
+               return;
 
-       /*
-        * Need to check ASC here; if it is "special," then
-        * the ASCQ is variable, and indicates failed component number.
-        * We must treat the ASCQ as a "don't care" while searching the
-        * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
-        * on when we actually need to identify the failed component.
-        */
-       if (SPECIAL_ASCQ(ASC,ASCQ))
-               ASCQ = 0xFF;
-
-       /* OK, now search mptscsih_ASCQ_Table[] for a matching entry */
-       for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
-               if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) {
-                       *s1 = mptscsih_ASCQ_TablePtr[idx].Description;
-                       return *s1;
-               }
+       vtarget->type = sdev->type;
 
-       if ((ASC >= 0x80) || (ASCQ >= 0x80))
-               *s1 = ascq_vendor_uniq;
-       else
-               *s1 = ascq_noone;
+       if (hd->ioc->bus_type != SPI)
+               return;
 
-       return *s1;
+       if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+               /* Treat all Processors as SAF-TE if
+                * command line option is set */
+               vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+               mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
+       }else if ((sdev->type == TYPE_PROCESSOR) &&
+               !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+               if (sdev->inquiry_len > 49 ) {
+                       if (sdev->inquiry[44] == 'S' &&
+                           sdev->inquiry[45] == 'A' &&
+                           sdev->inquiry[46] == 'F' &&
+                           sdev->inquiry[47] == '-' &&
+                           sdev->inquiry[48] == 'T' &&
+                           sdev->inquiry[49] == 'E' ) {
+                               vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+                               mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
+                       }
+               }
+       }
+       mptscsih_setTargetNegoParms(hd, vtarget, sdev);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *  SCSI Information Report; desired output format...
- *---
-SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION)
-  Key=6h (UNIT ATTENTION); FRU=03h
-  ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
-  CDB: 00 00 00 00 00 00 - TestUnitReady
- *---
- */
-/*
- *  SCSI Error Report; desired output format...
- *---
-SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
-  SCSI_Status=02h (CHECK CONDITION)
-  Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
-  SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
-  SenseKey=6h (UNIT ATTENTION); FRU=03h
-  ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
- *---
+ *  Update the target negotiation parameters based on the
+ *  the Inquiry data, adapter capabilities, and NVRAM settings.
+ *
  */
-
-int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
+static void
+mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
+                           struct scsi_device *sdev)
 {
-       char             foo[512];
-       char             buf2[32];
-       char            *statstr;
-       const char      *opstr;
-       int              sk             = SD_Sense_Key(ioop->sensePtr);
-       const char      *skstr          = SenseKeyString[sk];
-       unsigned char    asc            = SD_ASC(ioop->sensePtr);
-       unsigned char    ascq           = SD_ASCQ(ioop->sensePtr);
-       int              l;
-
-       /* Change the error logging to only report errors on
-        * read and write commands. Ignore errors on other commands.
-        * Should this be configurable via proc?
-        */
-       switch (ioop->cdbPtr[0]) {
-       case READ_6:
-       case WRITE_6:
-       case READ_10:
-       case WRITE_10:
-       case READ_12:
-       case WRITE_12:
-       case READ_16:
-       case WRITE_16:
-               break;
-       default:
-               return 0;
-       }
+       SpiCfgData *pspi_data = &hd->ioc->spi_data;
+       int  id = (int) target->target_id;
+       int  nvram;
+       u8 width = MPT_NARROW;
+       u8 factor = MPT_ASYNC;
+       u8 offset = 0;
+       u8 nfactor;
+       u8 noQas = 1;
 
-       /*
-        *  More quiet mode.
-        *  Filter out common, repetitive, warning-type errors...  like:
-        *    POWER ON (06,29/00 or 06,29/01),
-        *    SPINNING UP (02,04/01),
-        *    LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
-        */
-       if (sk == SK_NO_SENSE) {
-               return 0;
-       }
+       target->negoFlags = pspi_data->noQas;
 
-       if (    (sk==SK_UNIT_ATTENTION  && asc==0x29 && (ascq==0x00 || ascq==0x01))
-            || (sk==SK_NOT_READY       && asc==0x04 && (ascq==0x01 || ascq==0x02))
-            || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
-          )
-       {
-               /* Do nothing! */
-               return 0;
-       }
+       /* noQas == 0 => device supports QAS. */
 
-       /* Prevent the system from continually writing to the log
-        * if a medium is not found: 02 3A 00
-        * Changer issues: TUR, Read Capacity, Table of Contents continually
-        */
-       if (sk==SK_NOT_READY && asc==0x3A) {
-               if (ioop->cdbPtr == NULL) {
-                       return 0;
-               } else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
-                       (ioop->cdbPtr[0] == CMD_ReadCapacity) ||
-                       (ioop->cdbPtr[0] == 0x43)) {
-                       return 0;
+       if (sdev->scsi_level < SCSI_2) {
+               width = 0;
+               factor = MPT_ULTRA2;
+               offset = pspi_data->maxSyncOffset;
+               target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+       } else {
+               if (scsi_device_wide(sdev)) {
+                       width = 1;
                }
-       }
-       if (sk==SK_UNIT_ATTENTION) {
-               if (ioop->cdbPtr == NULL)
-                       return 0;
-               else if (ioop->cdbPtr[0] == CMD_TestUnitReady)
-                       return 0;
-       }
-
-       /*
-        *  Protect ourselves...
-        */
-       if (ioop->cdbPtr == NULL)
-               ioop->cdbPtr = dummyCDB;
-       if (ioop->sensePtr == NULL)
-               ioop->sensePtr = dummySenseData;
-       if (ioop->inqPtr == NULL)
-               ioop->inqPtr = dummyInqData;
-       if (ioop->dataPtr == NULL)
-               ioop->dataPtr = dummyScsiData;
-
-       statstr = NULL;
-       if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
-           ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
-               (void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
-               statstr = buf2;
-       }
 
-       opstr = NULL;
-       if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
-               opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
-       else if (mpt_ScsiOpcodesPtr)
-               opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
-
-       l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n",
-                         ioop->DevIDStr,
-                         ioop->SCSIStatus,
-                         statstr);
-       l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh",
-                 sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
-       {
-               const char      *x1, *x2, *x3, *x4;
-               x1 = x2 = x3 = x4 = "";
-               x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
-               if (x1 != NULL) {
-                       if (x1[0] != '(')
-                               l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
-                       else
-                               l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
-               }
-       }
-       l += sprintf(foo+l, "\n CDB:");
-       l += dump_cdb(foo+l, ioop->cdbPtr);
-       if (opstr)
-               l += sprintf(foo+l, " - \"%s\"", opstr);
-       l += sprintf(foo+l, "\n");
-
-       PrintF(("%s\n", foo));
-
-       return l;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     mptscsih_initTarget - Target, LUN alloc/free functionality.
- *     @hd: Pointer to MPT_SCSI_HOST structure
- *     @bus_id: Bus number (?)
- *     @target_id: SCSI target id
- *     @lun: SCSI LUN id
- *     @data: Pointer to data
- *     @dlen: Number of INQUIRY bytes
- *
- *     NOTE: It's only SAFE to call this routine if data points to
- *     sane & valid STANDARD INQUIRY data!
- *
- *     Allocate and initialize memory for this target.
- *     Save inquiry data.
- *
- */
-static void
-mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
-{
-       int             indexed_lun, lun_index;
-       VirtDevice      *vdev;
-       char            data_56;
-
-       dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
-                       hd->ioc->name, bus_id, target_id, lun, hd));
-
-       /* Is LUN supported? If so, upper 3 bits will be 0
-       * in first byte of inquiry data.
-       */
-       if (data[0] & 0xe0)
-               return;
-
-       vdev = hd->Targets[target_id];
-
-       lun_index = (lun >> 5);  /* 32 luns per lun_index */
-       indexed_lun = (lun % 32);
-       vdev->luns[lun_index] |= (1 << indexed_lun);
-
-       vdev->raidVolume = 0;
-       if (hd->is_spi) {
-               if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
-                       vdev->raidVolume = 1;
-                       ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
-               }
-       }
-
-       if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
-               if ( dlen > 8 ) {
-                       memcpy (vdev->inq_data, data, 8);
-               } else {
-                       memcpy (vdev->inq_data, data, dlen);
-               }
-               vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
-
-               /* If LUN 0, tape and have not done DV, set the DV flag.
-                */
-               if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) {
-                       ScsiCfgData *pSpi = &hd->ioc->spi_data;
-                       if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
-                               pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
-               }
-
-               if ( (data[0] == SCSI_TYPE_PROC) &&
-                       !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
-                       if ( dlen > 49 ) {
-                               vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
-                               if ( data[44] == 'S' &&
-                                    data[45] == 'A' &&
-                                    data[46] == 'F' &&
-                                    data[47] == '-' &&
-                                    data[48] == 'T' &&
-                                    data[49] == 'E' ) {
-                                       vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-                                       mptscsih_writeIOCPage4(hd, target_id, bus_id);
-                               }
-                       } else {
-                               /* Treat all Processors as SAF-TE if
-                                * command line option is set */
-                               if ( hd->ioc->spi_data.Saf_Te ) {
-                                       vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-                                       mptscsih_writeIOCPage4(hd, target_id, bus_id);
+               if (scsi_device_sync(sdev)) {
+                       factor = pspi_data->minSyncFactor;
+                       if (!scsi_device_dt(sdev))
+                                       factor = MPT_ULTRA2;
+                       else {
+                               if (!scsi_device_ius(sdev) &&
+                                   !scsi_device_qas(sdev))
+                                       factor = MPT_ULTRA160;
+                               else {
+                                       factor = MPT_ULTRA320;
+                                       if (scsi_device_qas(sdev)) {
+                                               ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
+                                               noQas = 0;
+                                       }
+                                       if (sdev->type == TYPE_TAPE &&
+                                           scsi_device_ius(sdev))
+                                               target->negoFlags |= MPT_TAPE_NEGO_IDP;
                                }
                        }
-               }
+                       offset = pspi_data->maxSyncOffset;
 
-               data_56 = 0;
-               if (dlen > 56) {
-                       if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
-                       /* Update the target capabilities
+                       /* If RAID, never disable QAS
+                        * else if non RAID, do not disable
+                        *   QAS if bit 1 is set
+                        * bit 1 QAS support, non-raid only
+                        * bit 0 IU support
                         */
-                               data_56 = data[56];
-                               vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
+                       if (target->raidVolume == 1) {
+                               noQas = 0;
                        }
+               } else {
+                       factor = MPT_ASYNC;
+                       offset = 0;
                }
-               mptscsih_setTargetNegoParms(hd, vdev, data_56);
        }
 
-       dprintk((KERN_INFO "  target = %p\n", vdev));
-       return;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Update the target negotiation parameters based on the
- *  the Inquiry data, adapter capabilities, and NVRAM settings.
- *
- */
-void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
-{
-       ScsiCfgData *pspi_data = &hd->ioc->spi_data;
-       int  id = (int) target->target_id;
-       int  nvram;
-       char canQ = 0;
-       VirtDevice      *vdev;
-       int ii;
-       u8 width = MPT_NARROW;
-       u8 factor = MPT_ASYNC;
-       u8 offset = 0;
-       u8 version, nfactor;
-       u8 noQas = 1;
-
-       if (!hd->is_spi) {
-               if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-                       if (target->inq_data[7] & 0x02)
-                               target->tflags |= MPT_TARGET_FLAGS_Q_YES;
-               }
-               return;
+       if (!sdev->tagged_supported) {
+               target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
        }
 
-       target->negoFlags = pspi_data->noQas;
-
-       /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
-        * support. If available, default QAS to off and allow enabling.
-        * If not available, default QAS to on, turn off for non-disks.
-        */
-
-       /* Set flags based on Inquiry data
+       /* Update tflags based on NVRAM settings. (SCSI only)
         */
-       if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-               version = target->inq_data[2] & 0x07;
-               if (version < 2) {
-                       width = 0;
-                       factor = MPT_ULTRA2;
-                       offset = pspi_data->maxSyncOffset;
-               } else {
-                       if (target->inq_data[7] & 0x20) {
-                               width = 1;
-                       }
+       if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+               nvram = pspi_data->nvram[id];
+               nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
 
-                       if (target->inq_data[7] & 0x10) {
-                               /* bits 2 & 3 show DT support
-                                */
-                               if ((byte56 & 0x04) == 0)
-                                       factor = MPT_ULTRA2;
-                               else if ((byte56 & 0x03) == 0)
-                                       factor = MPT_ULTRA160;
-                               else
-                                       factor = MPT_ULTRA320;
-                               offset = pspi_data->maxSyncOffset;
-
-                               /* If RAID, never disable QAS
-                                * else if non RAID, do not disable
-                                *   QAS if bit 1 is set
-                                * bit 1 QAS support, non-raid only
-                                * bit 0 IU support
-                                */
-                               if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
-                                       noQas = 0;
-                       } else {
-                               factor = MPT_ASYNC;
-                               offset = 0;
-                       }
-               }
-
-               if (target->inq_data[7] & 0x02) {
-                       canQ = 1;
-               }
-
-               /* Update tflags based on NVRAM settings. (SCSI only)
-                */
-               if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-                       nvram = pspi_data->nvram[id];
-                       nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
+               if (width)
+                       width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
 
-                       if (width)
-                               width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+               if (offset > 0) {
+                       /* Ensure factor is set to the
+                        * maximum of: adapter, nvram, inquiry
+                        */
+                       if (nfactor) {
+                               if (nfactor < pspi_data->minSyncFactor )
+                                       nfactor = pspi_data->minSyncFactor;
 
-                       if (offset > 0) {
-                               /* Ensure factor is set to the
-                                * maximum of: adapter, nvram, inquiry
-                                */
-                               if (nfactor) {
-                                       if (nfactor < pspi_data->minSyncFactor )
-                                               nfactor = pspi_data->minSyncFactor;
-
-                                       factor = max(factor, nfactor);
-                                       if (factor == MPT_ASYNC)
-                                               offset = 0;
-                               } else {
+                               factor = max(factor, nfactor);
+                               if (factor == MPT_ASYNC)
                                        offset = 0;
-                                       factor = MPT_ASYNC;
-                               }
                        } else {
+                               offset = 0;
                                factor = MPT_ASYNC;
-                       }
-               }
-
-               /* Make sure data is consistent
-                */
-               if ((!width) && (factor < MPT_ULTRA2)) {
-                       factor = MPT_ULTRA2;
                }
-
-               /* Save the data to the target structure.
-                */
-               target->minSyncFactor = factor;
-               target->maxOffset = offset;
-               target->maxWidth = width;
-               if (canQ) {
-                       target->tflags |= MPT_TARGET_FLAGS_Q_YES;
+               } else {
+                       factor = MPT_ASYNC;
                }
+       }
 
-               target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
-
-               /* Disable unused features.
-                */
-               if (!width)
-                       target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
-               if (!offset)
-                       target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+       /* Make sure data is consistent
+        */
+       if ((!width) && (factor < MPT_ULTRA2)) {
+               factor = MPT_ULTRA2;
+       }
 
-               /* GEM, processor WORKAROUND
-                */
-               if (((target->inq_data[0] & 0x1F) == 0x03)
-                       || ((target->inq_data[0] & 0x1F) > 0x08)) {
-                       target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
-                       pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
-               } else {
-                       if (noQas && (pspi_data->noQas == 0)) {
-                               pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
-                               target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+       /* Save the data to the target structure.
+        */
+       target->minSyncFactor = factor;
+       target->maxOffset = offset;
+       target->maxWidth = width;
 
-                               /* Disable QAS in a mixed configuration case
-                               */
+       target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
 
-//                             ddvtprintk((KERN_INFO "Disabling QAS!\n"));
-                               for (ii = 0; ii < id; ii++) {
-                                       if ( (vdev = hd->Targets[ii]) ) {
-                                               vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-                                       }
-                               }
-                       }
-               }
-       }
+       /* Disable unused features.
+        */
+       if (!width)
+               target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
 
-       return;
-}
+       if (!offset)
+               target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
- * Else set the NEED_DV flag after Read Capacity Issued (disks)
- * or Mode Sense (cdroms).
- *
- * Tapes, initTarget will set this flag on completion of Inquiry command.
- * Called only if DV_NOT_DONE flag is set
- */
-static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
-{
-       u8 cmd;
+       if ( factor > MPT_ULTRA320 )
+               noQas = 0;
 
-       if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
-               return;
+       if (noQas && (pspi_data->noQas == 0)) {
+               pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+               target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
 
-       cmd = pReq->CDB[0];
+               /* Disable QAS in a mixed configuration case
+                */
 
-       if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
-               ScsiCfgData *pSpi = &hd->ioc->spi_data;
-               if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
-                       /* Set NEED_DV for all hidden disks
-                        */
-                       Ioc3PhysDisk_t *pPDisk =  pSpi->pIocPg3->PhysDisk;
-                       int             numPDisk = pSpi->pIocPg3->NumPhysDisks;
-
-                       while (numPDisk) {
-                               pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
-                               ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
-                               pPDisk++;
-                               numPDisk--;
-                       }
-               }
-               pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
-               ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
+               ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
        }
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * If no Target, bus reset on 1st I/O. Set the flag to
- * prevent any future negotiations to this device.
- */
-static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
-{
-
-       if ((hd->Targets) && (hd->Targets[target_id] == NULL))
-               hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
-
-       return;
-}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  SCSI Config Page functionality ...
  */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_setDevicePage1Flags  - add Requested and Configuration fields flags
- *     based on width, factor and offset parameters.
- *     @width: bus width
- *     @factor: sync factor
- *     @offset: sync offset
- *     @requestedPtr: pointer to requested values (updated)
- *     @configurationPtr: pointer to configuration values (updated)
- *     @flags: flags to block WDTR or SDTR negotiation
- *
- *     Return: None.
- *
- *     Remark: Called by writeSDP1 and _dv_params
- */
-static void
-mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
-{
-       u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
-       u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
-
-       *configurationPtr = 0;
-       *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
-       *requestedPtr |= (offset << 16) | (factor << 8);
-
-       if (width && offset && !nowide && !nosync) {
-               if (factor < MPT_ULTRA160) {
-                       *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
-                       if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
-                               *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
-               } else if (factor < MPT_ULTRA2) {
-                       *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
-               }
-       }
-
-       if (nowide)
-               *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
-
-       if (nosync)
-               *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
-
-       return;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_writeSDP1  - write SCSI Device Page 1
- *     @hd: Pointer to a SCSI Host Strucutre
- *     @portnum: IOC port number
- *     @target_id: writeSDP1 for single ID
- *     @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
- *
- *     Return: -EFAULT if read of config page header fails
- *             or 0 if success.
- *
- *     Remark: If a target has been found, the settings from the
- *             target structure are used, else the device is set
- *             to async/narrow.
- *
- *     Remark: Called during init and after a FW reload.
- *     Remark: We do not wait for a return, write pages sequentially.
- */
-static int
-mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
-{
-       MPT_ADAPTER             *ioc = hd->ioc;
-       Config_t                *pReq;
-       SCSIDevicePage1_t       *pData;
-       VirtDevice              *pTarget;
-       MPT_FRAME_HDR           *mf;
-       dma_addr_t               dataDma;
-       u16                      req_idx;
-       u32                      frameOffset;
-       u32                      requested, configuration, flagsLength;
-       int                      ii, nvram;
-       int                      id = 0, maxid = 0;
-       u8                       width;
-       u8                       factor;
-       u8                       offset;
-       u8                       bus = 0;
-       u8                       negoFlags;
-       u8                       maxwidth, maxoffset, maxfactor;
-
-       if (ioc->spi_data.sdp1length == 0)
-               return 0;
-
-       if (flags & MPT_SCSICFG_ALL_IDS) {
-               id = 0;
-               maxid = ioc->sh->max_id - 1;
-       } else if (ioc->sh) {
-               id = target_id;
-               maxid = min_t(int, id, ioc->sh->max_id - 1);
-       }
-
-       for (; id <= maxid; id++) {
-
-               if (id == ioc->pfacts[portnum].PortSCSIID)
-                       continue;
-
-               /* Use NVRAM to get adapter and target maximums
-                * Data over-riden by target structure information, if present
-                */
-               maxwidth = ioc->spi_data.maxBusWidth;
-               maxoffset = ioc->spi_data.maxSyncOffset;
-               maxfactor = ioc->spi_data.minSyncFactor;
-               if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-                       nvram = ioc->spi_data.nvram[id];
-
-                       if (maxwidth)
-                               maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
-
-                       if (maxoffset > 0) {
-                               maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
-                               if (maxfactor == 0) {
-                                       /* Key for async */
-                                       maxfactor = MPT_ASYNC;
-                                       maxoffset = 0;
-                               } else if (maxfactor < ioc->spi_data.minSyncFactor) {
-                                       maxfactor = ioc->spi_data.minSyncFactor;
-                               }
-                       } else
-                               maxfactor = MPT_ASYNC;
-               }
-
-               /* Set the negotiation flags.
-                */
-               negoFlags = ioc->spi_data.noQas;
-               if (!maxwidth)
-                       negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
-               if (!maxoffset)
-                       negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
-
-               if (flags & MPT_SCSICFG_USE_NVRAM) {
-                       width = maxwidth;
-                       factor = maxfactor;
-                       offset = maxoffset;
-               } else {
-                       width = 0;
-                       factor = MPT_ASYNC;
-                       offset = 0;
-                       //negoFlags = 0;
-                       //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
-               }
-
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-               /* Force to async and narrow if DV has not been executed
-                * for this ID
-                */
-               if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
-                       width = 0;
-                       factor = MPT_ASYNC;
-                       offset = 0;
-               }
-#endif
-
-               /* If id is not a raid volume, get the updated
-                * transmission settings from the target structure.
-                */
-               if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
-                       width = pTarget->maxWidth;
-                       factor = pTarget->minSyncFactor;
-                       offset = pTarget->maxOffset;
-                       negoFlags = pTarget->negoFlags;
-               }
-
-               if (flags & MPT_SCSICFG_BLK_NEGO)
-                       negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
-
-               mptscsih_setDevicePage1Flags(width, factor, offset,
-                                       &requested, &configuration, negoFlags);
-
-               /* Get a MF for this command.
-                */
-               if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
-                       dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
-                                               ioc->name));
-                       return -EAGAIN;
-               }
-
-               ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
-                       hd->ioc->name, mf, id, requested, configuration));
-
-
-               /* Set the request and the data pointers.
-                * Request takes: 36 bytes (32 bit SGE)
-                * SCSI Device Page 1 requires 16 bytes
-                * 40 + 16 <= size of SCSI IO Request = 56 bytes
-                * and MF size >= 64 bytes.
-                * Place data at end of MF.
-                */
-               pReq = (Config_t *)mf;
-
-               req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-               frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
-
-               pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
-               dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
-
-               /* Complete the request frame (same for all requests).
-                */
-               pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-               pReq->Reserved = 0;
-               pReq->ChainOffset = 0;
-               pReq->Function = MPI_FUNCTION_CONFIG;
-               pReq->ExtPageLength = 0;
-               pReq->ExtPageType = 0;
-               pReq->MsgFlags = 0;
-               for (ii=0; ii < 8; ii++) {
-                       pReq->Reserved2[ii] = 0;
-               }
-               pReq->Header.PageVersion = ioc->spi_data.sdp1version;
-               pReq->Header.PageLength = ioc->spi_data.sdp1length;
-               pReq->Header.PageNumber = 1;
-               pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-               pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
-
-               /* Add a SGE to the config request.
-                */
-               flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
-
-               mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
-
-               /* Set up the common data portion
-                */
-               pData->Header.PageVersion = pReq->Header.PageVersion;
-               pData->Header.PageLength = pReq->Header.PageLength;
-               pData->Header.PageNumber = pReq->Header.PageNumber;
-               pData->Header.PageType = pReq->Header.PageType;
-               pData->RequestedParameters = cpu_to_le32(requested);
-               pData->Reserved = 0;
-               pData->Configuration = cpu_to_le32(configuration);
-
-               dprintk((MYIOC_s_INFO_FMT
-                       "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
-                               ioc->name, id, (id | (bus<<8)),
-                               requested, configuration));
-
-               mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
-       }
-
-       return 0;
-}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*     mptscsih_writeIOCPage4  - write IOC Page 4
@@ -4874,15 +2909,12 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
 
        /* Get a MF for this command.
         */
-       if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
-               dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
+       if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
+               dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
                                        ioc->name));
                return -EAGAIN;
        }
 
-       ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n",
-               ioc->name, mf, target_id));
-
        /* Set the request and the data pointers.
         * Place data at end of MF.
         */
@@ -4919,69 +2951,15 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
 
        mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
 
-       dsprintk((MYIOC_s_INFO_FMT
-               "writeIOCPage4: pgaddr 0x%x\n",
-                       ioc->name, (target_id | (bus<<8))));
+       dinitprintk((MYIOC_s_INFO_FMT
+               "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
+                       ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
 
-       mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
+       mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
 
        return 0;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_taskmgmt_timeout - Call back for timeout on a
- *     task management request.
- *     @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
- *
- */
-static void mptscsih_taskmgmt_timeout(unsigned long data)
-{
-       MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
-
-       dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
-                  "TM request timed out!\n", hd->ioc->name));
-
-       /* Delete the timer that triggered this callback.
-        * Remark: del_timer checks to make sure timer is active
-        * before deleting.
-        */
-       del_timer(&hd->TMtimer);
-
-       /* Call the reset handler. Already had a TM request
-        * timeout - so issue a diagnostic reset
-        */
-       MPT_INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
-       SCHEDULE_TASK(&mptscsih_rstTask);
-       return;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_schedule_reset - Call back for timeout on a
- *     task management request.
- *     @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
- *
- */
-static void
-mptscsih_schedule_reset(void *arg)
-{
-        MPT_SCSI_HOST           *hd;
-        hd = (MPT_SCSI_HOST *) arg;
-
-       if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
-               printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
-       } else {
-               /* Because we have reset the IOC, no TM requests can be
-                * pending.  So let's make sure the tmPending flag is reset.
-                */
-               dtmprintk((KERN_WARNING MYNAM
-                          ": %s: mptscsih_taskmgmt_timeout\n",
-                          hd->ioc->name));
-               hd->tmPending = 0;
-       }
-
-       return;
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  Bus Scan and Domain Validation functionality ...
@@ -5007,7 +2985,7 @@ mptscsih_schedule_reset(void *arg)
  *     in the IOC member localReply structure.
  *     Used ONLY for DV and other internal commands.
  */
-static int
+int
 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 {
        MPT_SCSI_HOST   *hd;
@@ -5015,6 +2993,8 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
        int              completionCode;
        u16              req_idx;
 
+       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+
        if ((mf == NULL) ||
            (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
                printk(MYIOC_s_ERR_FMT
@@ -5023,7 +3003,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                goto wakeup;
        }
 
-       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
        del_timer(&hd->timer);
        req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
        hd->ScsiLookup[req_idx] = NULL;
@@ -5048,13 +3027,15 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
        } else {
                SCSIIOReply_t   *pReply;
                u16              status;
+               u8               scsi_status;
 
                pReply = (SCSIIOReply_t *) mr;
 
                status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+               scsi_status = pReply->SCSIStatus;
 
                ddvtprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
-                            status, pReply->SCSIState, pReply->SCSIStatus,
+                            status, pReply->SCSIState, scsi_status,
                             le32_to_cpu(pReply->IOCLogInfo)));
 
                switch(status) {
@@ -5087,10 +3068,11 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                 * some type of error occurred.
                                 */
                                MpiRaidActionReply_t    *pr = (MpiRaidActionReply_t *)mr;
-                               if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
+                               if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
                                        completionCode = MPT_SCANDV_GOOD;
                                else
                                        completionCode = MPT_SCANDV_SOME_ERROR;
+                               memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
 
                        } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
                                u8              *sense_data;
@@ -5099,7 +3081,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                /* save sense data in global structure
                                 */
                                completionCode = MPT_SCANDV_SENSE;
-                               hd->pLocal->scsiStatus = pReply->SCSIStatus;
+                               hd->pLocal->scsiStatus = scsi_status;
                                sense_data = ((u8 *)hd->ioc->sense_buf_pool +
                                        (req_idx * MPT_SENSE_BUFFER_ALLOC));
 
@@ -5110,7 +3092,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                                ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
                                                sense_data));
                        } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
-                               if (pReq->CDB[0] == CMD_Inquiry)
+                               if (pReq->CDB[0] == INQUIRY)
                                        completionCode = MPT_SCANDV_ISSUE_SENSE;
                                else
                                        completionCode = MPT_SCANDV_DID_RESET;
@@ -5120,11 +3102,8 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
                                completionCode = MPT_SCANDV_DID_RESET;
                        else {
-                               /* If no error, this will be equivalent
-                                * to MPT_SCANDV_GOOD
-                                */
                                completionCode = MPT_SCANDV_GOOD;
-                               hd->pLocal->scsiStatus = pReply->SCSIStatus;
+                               hd->pLocal->scsiStatus = scsi_status;
                        }
                        break;
 
@@ -5151,13 +3130,13 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
         */
 wakeup:
        /* Free Chain buffers (will never chain) in scan or dv */
-       //mptscsih_freeChainBuffers(hd, req_idx);
+       //mptscsih_freeChainBuffers(ioc, req_idx);
 
        /*
         * Wake up the original calling thread
         */
-       scandv_wait_done = 1;
-       wake_up(&scandv_waitq);
+       hd->scandv_wait_done = 1;
+       wake_up(&hd->scandv_waitq);
 
        return 1;
 }
@@ -5168,7 +3147,8 @@ wakeup:
  *     @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
  *
  */
-static void mptscsih_timer_expired(unsigned long data)
+void
+mptscsih_timer_expired(unsigned long data)
 {
        MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
 
@@ -5206,78 +3186,6 @@ static void mptscsih_timer_expired(unsigned long data)
        return;
 }
 
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_do_raid - Format and Issue a RAID volume request message.
- *     @hd: Pointer to scsi host structure
- *     @action: What do be done.
- *     @id: Logical target id.
- *     @bus: Target locations bus.
- *
- *     Returns: < 0 on a fatal error
- *             0 on success
- *
- *     Remark: Wait to return until reply processed by the ISR.
- */
-static int
-mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
-{
-       MpiRaidActionRequest_t  *pReq;
-       MPT_FRAME_HDR           *mf;
-       int                     in_isr;
-
-       in_isr = in_interrupt();
-       if (in_isr) {
-               dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
-                                       hd->ioc->name));
-               return -EPERM;
-       }
-
-       /* Get and Populate a free Frame
-        */
-       if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
-               ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
-                                       hd->ioc->name));
-               return -EAGAIN;
-       }
-       pReq = (MpiRaidActionRequest_t *)mf;
-       pReq->Action = action;
-       pReq->Reserved1 = 0;
-       pReq->ChainOffset = 0;
-       pReq->Function = MPI_FUNCTION_RAID_ACTION;
-       pReq->VolumeID = io->id;
-       pReq->VolumeBus = io->bus;
-       pReq->PhysDiskNum = io->physDiskNum;
-       pReq->MsgFlags = 0;
-       pReq->Reserved2 = 0;
-       pReq->ActionDataWord = 0; /* Reserved for this action */
-       //pReq->ActionDataSGE = 0;
-
-       mpt_add_sge((char *)&pReq->ActionDataSGE,
-               MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
-
-       ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
-                       hd->ioc->name, action, io->id));
-
-       hd->pLocal = NULL;
-       hd->timer.expires = jiffies + HZ*2; /* 2 second timeout */
-       scandv_wait_done = 0;
-
-       /* Save cmd pointer, for resource free if timeout or
-        * FW reload occurs
-        */
-       hd->cmdPtr = mf;
-
-       add_timer(&hd->timer);
-       mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
-       wait_event(scandv_waitq, scandv_wait_done);
-
-       if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
-               return -1;
-
-       return 0;
-}
-#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -5323,7 +3231,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
        /* Set command specific information
         */
        switch (cmd) {
-       case CMD_Inquiry:
+       case INQUIRY:
                cmdLen = 6;
                dir = MPI_SCSIIO_CONTROL_READ;
                CDB[0] = cmd;
@@ -5331,13 +3239,13 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
                cmdTimeout = 10;
                break;
 
-       case CMD_TestUnitReady:
+       case TEST_UNIT_READY:
                cmdLen = 6;
                dir = MPI_SCSIIO_CONTROL_READ;
                cmdTimeout = 10;
                break;
 
-       case CMD_StartStopUnit:
+       case START_STOP:
                cmdLen = 6;
                dir = MPI_SCSIIO_CONTROL_READ;
                CDB[0] = cmd;
@@ -5345,7 +3253,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
                cmdTimeout = 15;
                break;
 
-       case CMD_RequestSense:
+       case REQUEST_SENSE:
                cmdLen = 6;
                CDB[0] = cmd;
                CDB[4] = io->size;
@@ -5353,7 +3261,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
                cmdTimeout = 10;
                break;
 
-       case CMD_ReadBuffer:
+       case READ_BUFFER:
                cmdLen = 10;
                dir = MPI_SCSIIO_CONTROL_READ;
                CDB[0] = cmd;
@@ -5372,7 +3280,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
                cmdTimeout = 10;
                break;
 
-       case CMD_WriteBuffer:
+       case WRITE_BUFFER:
                cmdLen = 10;
                dir = MPI_SCSIIO_CONTROL_WRITE;
                CDB[0] = cmd;
@@ -5387,21 +3295,21 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
                cmdTimeout = 10;
                break;
 
-       case CMD_Reserve6:
+       case RESERVE:
                cmdLen = 6;
                dir = MPI_SCSIIO_CONTROL_READ;
                CDB[0] = cmd;
                cmdTimeout = 10;
                break;
 
-       case CMD_Release6:
+       case RELEASE:
                cmdLen = 6;
                dir = MPI_SCSIIO_CONTROL_READ;
                CDB[0] = cmd;
                cmdTimeout = 10;
                break;
 
-       case CMD_SynchronizeCache:
+       case SYNCHRONIZE_CACHE:
                cmdLen = 10;
                dir = MPI_SCSIIO_CONTROL_READ;
                CDB[0] = cmd;
@@ -5416,7 +3324,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 
        /* Get and Populate a free Frame
         */
-       if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
+       if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
                ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
                                        hd->ioc->name));
                return -EBUSY;
@@ -5457,7 +3365,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
        else
                pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
 
-       if (cmd == CMD_RequestSense) {
+       if (cmd == REQUEST_SENSE) {
                pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
                ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
                        hd->ioc->name, cmd));
@@ -5498,7 +3406,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
         */
        hd->pLocal = NULL;
        hd->timer.expires = jiffies + HZ*cmdTimeout;
-       scandv_wait_done = 0;
+       hd->scandv_wait_done = 0;
 
        /* Save cmd pointer, for resource free if timeout or
         * FW reload occurs
@@ -5506,8 +3414,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
        hd->cmdPtr = mf;
 
        add_timer(&hd->timer);
-       mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
-       wait_event(scandv_waitq, scandv_wait_done);
+       mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+       wait_event(hd->scandv_waitq, hd->scandv_wait_done);
 
        if (hd->pLocal) {
                rc = hd->pLocal->completion;
@@ -5532,1747 +3440,63 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
- *     @hd: Pointer to MPT_SCSI_HOST structure
- *     @portnum: IOC port number
+ *     @hd: Pointer to a SCSI HOST structure
+ *     @vdevice: virtual target device
  *
  *     Uses the ISR, but with special processing.
  *     MUST be single-threaded.
  *
- *     Return: 0 on completion
  */
-static int
-mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
+static void
+mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 {
-       MPT_ADAPTER             *ioc= hd->ioc;
-       VirtDevice              *pTarget;
-       SCSIDevicePage1_t       *pcfg1Data = NULL;
        INTERNAL_CMD             iocmd;
-       CONFIGPARMS              cfg;
-       dma_addr_t               cfg1_dma_addr = -1;
-       ConfigPageHeader_t       header1;
-       int                      bus = 0;
-       int                      id = 0;
-       int                      lun;
-       int                      indexed_lun, lun_index;
-       int                      hostId = ioc->pfacts[portnum].PortSCSIID;
-       int                      max_id;
-       int                      requested, configuration, data;
-       int                      doConfig = 0;
-       u8                       flags, factor;
-
-       max_id = ioc->sh->max_id - 1;
 
        /* Following parameters will not change
         * in this routine.
         */
-       iocmd.cmd = CMD_SynchronizeCache;
+       iocmd.cmd = SYNCHRONIZE_CACHE;
        iocmd.flags = 0;
        iocmd.physDiskNum = -1;
        iocmd.data = NULL;
        iocmd.data_dma = -1;
        iocmd.size = 0;
        iocmd.rsvd = iocmd.rsvd2 = 0;
+       iocmd.bus = vdevice->vtarget->bus_id;
+       iocmd.id = vdevice->vtarget->target_id;
+       iocmd.lun = (u8)vdevice->lun;
 
-       /* No SCSI hosts
-        */
-       if (hd->Targets == NULL)
-               return 0;
-
-       /* Skip the host
-        */
-       if (id == hostId)
-               id++;
-
-       /* Write SDP1 for all SCSI devices
-        * Alloc memory and set up config buffer
-        */
-       if (hd->is_spi) {
-               if (ioc->spi_data.sdp1length > 0) {
-                       pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
-                                        ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
-
-                       if (pcfg1Data != NULL) {
-                               doConfig = 1;
-                               header1.PageVersion = ioc->spi_data.sdp1version;
-                               header1.PageLength = ioc->spi_data.sdp1length;
-                               header1.PageNumber = 1;
-                               header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-                               cfg.hdr = &header1;
-                               cfg.physAddr = cfg1_dma_addr;
-                               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-                               cfg.dir = 1;
-                               cfg.timeout = 0;
-                       }
-               }
-       }
-
-       /* loop through all devices on this port
-        */
-       while (bus < MPT_MAX_BUS) {
-               iocmd.bus = bus;
-               iocmd.id = id;
-               pTarget = hd->Targets[(int)id];
-
-               if (doConfig) {
-
-                       /* Set the negotiation flags */
-                       if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
-                               flags = pTarget->negoFlags;
-                       } else {
-                               flags = hd->ioc->spi_data.noQas;
-                               if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-                                       data = hd->ioc->spi_data.nvram[id];
-
-                                       if (data & MPT_NVRAM_WIDE_DISABLE)
-                                               flags |= MPT_TARGET_NO_NEGO_WIDE;
-
-                                       factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
-                                       if ((factor == 0) || (factor == MPT_ASYNC))
-                                               flags |= MPT_TARGET_NO_NEGO_SYNC;
-                               }
-                       }
-
-                       /* Force to async, narrow */
-                       mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
-                                       &configuration, flags);
-                       pcfg1Data->RequestedParameters = le32_to_cpu(requested);
-                       pcfg1Data->Reserved = 0;
-                       pcfg1Data->Configuration = le32_to_cpu(configuration);
-                       cfg.pageAddr = (bus<<8) | id;
-                       mpt_config(hd->ioc, &cfg);
-               }
-
-               /* If target Ptr NULL or if this target is NOT a disk, skip.
-                */
-               if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
-                       for (lun=0; lun <= MPT_LAST_LUN; lun++) {
-                               /* If LUN present, issue the command
-                                */
-                               lun_index = (lun >> 5);  /* 32 luns per lun_index */
-                               indexed_lun = (lun % 32);
-                               if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
-                                       iocmd.lun = lun;
-                                       (void) mptscsih_do_cmd(hd, &iocmd);
-                               }
-                       }
-               }
-
-               /* get next relevant device */
-               id++;
-
-               if (id == hostId)
-                       id++;
-
-               if (id > max_id) {
-                       id = 0;
-                       bus++;
-               }
-       }
-
-       if (pcfg1Data) {
-               pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
-       }
-
-       return 0;
-}
-
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mptscsih_domainValidation - Top level handler for domain validation.
- *     @hd: Pointer to MPT_SCSI_HOST structure.
- *
- *     Uses the ISR, but with special processing.
- *     Called from schedule, should not be in interrupt mode.
- *     While thread alive, do dv for all devices needing dv
- *
- *     Return: None.
- */
-static void
-mptscsih_domainValidation(void *arg)
-{
-       MPT_SCSI_HOST           *hd;
-       MPT_ADAPTER             *ioc;
-       unsigned long            flags;
-       int                      id, maxid, dvStatus, did;
-       int                      ii, isPhysDisk;
-
-       spin_lock_irqsave(&dvtaskQ_lock, flags);
-       dvtaskQ_active = 1;
-       if (dvtaskQ_release) {
-               dvtaskQ_active = 0;
-               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-               return;
-       }
-       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
-       /* For this ioc, loop through all devices and do dv to each device.
-        * When complete with this ioc, search through the ioc list, and
-        * for each scsi ioc found, do dv for all devices. Exit when no
-        * device needs dv.
-        */
-       did = 1;
-       while (did) {
-               did = 0;
-               for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
-                       spin_lock_irqsave(&dvtaskQ_lock, flags);
-                       if (dvtaskQ_release) {
-                               dvtaskQ_active = 0;
-                               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-                               return;
-                       }
-                       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(HZ/4);
-
-                       /* DV only to SCSI adapters */
-                       if ((int)ioc->chip_type <= (int)FC929)
-                               continue;
-
-                       /* Make sure everything looks ok */
-                       if (ioc->sh == NULL)
-                               continue;
-
-                       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-                       if (hd == NULL)
-                               continue;
-
-                       if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
-                               mpt_read_ioc_pg_3(ioc);
-                               if (ioc->spi_data.pIocPg3) {
-                                       Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
-                                       int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
-
-                                       while (numPDisk) {
-                                               if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
-                                                       ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
-
-                                               pPDisk++;
-                                               numPDisk--;
-                                       }
-                               }
-                               ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
-                       }
-
-                       maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
-
-                       for (id = 0; id < maxid; id++) {
-                               spin_lock_irqsave(&dvtaskQ_lock, flags);
-                               if (dvtaskQ_release) {
-                                       dvtaskQ_active = 0;
-                                       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-                                       return;
-                               }
-                               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-                               dvStatus = hd->ioc->spi_data.dvStatus[id];
-
-                               if (dvStatus & MPT_SCSICFG_NEED_DV) {
-                                       did++;
-                                       hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
-                                       hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
-
-                                       set_current_state(TASK_INTERRUPTIBLE);
-                                       schedule_timeout(HZ/4);
-
-                                       /* If hidden phys disk, block IO's to all
-                                        *      raid volumes
-                                        * else, process normally
-                                        */
-                                       isPhysDisk = mptscsih_is_phys_disk(ioc, id);
-                                       if (isPhysDisk) {
-                                               for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-                                                       if (hd->ioc->spi_data.isRaid & (1 << ii)) {
-                                                               hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
-                                                       }
-                                               }
-                                       }
-
-                                       if (mptscsih_doDv(hd, 0, id) == 1) {
-                                               /* Untagged device was busy, try again
-                                                */
-                                               hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
-                                               hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
-                                       } else {
-                                               /* DV is complete. Clear flags.
-                                                */
-                                               hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
-                                       }
-
-                                       if (isPhysDisk) {
-                                               for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-                                                       if (hd->ioc->spi_data.isRaid & (1 << ii)) {
-                                                               hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
-                                                       }
-                                               }
-                                       }
-
-                                       /* Post OS IOs that were pended while
-                                        * DV running.
-                                        */
-                                       post_pendingQ_commands(hd);
-
-                                       if (hd->ioc->spi_data.noQas)
-                                               mptscsih_qas_check(hd, id);
-                               }
-                       }
-               }
-       }
-
-       spin_lock_irqsave(&dvtaskQ_lock, flags);
-       dvtaskQ_active = 0;
-       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
-       return;
-}
-
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
-static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
-{
-       if (ioc->spi_data.pIocPg3) {
-               Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
-               int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
-
-               while (numPDisk) {
-                       if (pPDisk->PhysDiskID == id) {
-                               return 1;
-                       }
-                       pPDisk++;
-                       numPDisk--;
-               }
-       }
-       return 0;
-}
-
-/* Write SDP1 if no QAS has been enabled
- */
-static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
-{
-       VirtDevice *pTarget;
-       int ii;
-
-       if (hd->Targets == NULL)
-               return;
-
-       for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-               if (ii == id)
-                       continue;
-
-               if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
-                       continue;
-
-               pTarget = hd->Targets[ii];
-
-               if ((pTarget != NULL) && (!pTarget->raidVolume)) {
-                       if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
-                               pTarget->negoFlags |= hd->ioc->spi_data.noQas;
-                               mptscsih_writeSDP1(hd, 0, ii, 0);
-                       }
-               } else {
-                       if (mptscsih_is_phys_disk(hd->ioc, ii) == 1)
-                               mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
-               }
-       }
-       return;
+       if ((vdevice->vtarget->type == TYPE_DISK) &&
+           (vdevice->configured_lun))
+               mptscsih_do_cmd(hd, &iocmd);
 }
 
-
-
-#define MPT_GET_NVRAM_VALS     0x01
-#define MPT_UPDATE_MAX         0x02
-#define MPT_SET_MAX            0x04
-#define MPT_SET_MIN            0x08
-#define MPT_FALLBACK           0x10
-#define MPT_SAVE               0x20
+EXPORT_SYMBOL(mptscsih_remove);
+EXPORT_SYMBOL(mptscsih_shutdown);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(mptscsih_suspend);
+EXPORT_SYMBOL(mptscsih_resume);
+#endif
+EXPORT_SYMBOL(mptscsih_proc_info);
+EXPORT_SYMBOL(mptscsih_info);
+EXPORT_SYMBOL(mptscsih_qcmd);
+EXPORT_SYMBOL(mptscsih_target_alloc);
+EXPORT_SYMBOL(mptscsih_slave_alloc);
+EXPORT_SYMBOL(mptscsih_target_destroy);
+EXPORT_SYMBOL(mptscsih_slave_destroy);
+EXPORT_SYMBOL(mptscsih_slave_configure);
+EXPORT_SYMBOL(mptscsih_abort);
+EXPORT_SYMBOL(mptscsih_dev_reset);
+EXPORT_SYMBOL(mptscsih_bus_reset);
+EXPORT_SYMBOL(mptscsih_host_reset);
+EXPORT_SYMBOL(mptscsih_bios_param);
+EXPORT_SYMBOL(mptscsih_io_done);
+EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
+EXPORT_SYMBOL(mptscsih_scandv_complete);
+EXPORT_SYMBOL(mptscsih_event_process);
+EXPORT_SYMBOL(mptscsih_ioc_reset);
+EXPORT_SYMBOL(mptscsih_change_queue_depth);
+EXPORT_SYMBOL(mptscsih_timer_expired);
+EXPORT_SYMBOL(mptscsih_TMHandler);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *     mptscsih_doDv - Perform domain validation to a target.
- *     @hd: Pointer to MPT_SCSI_HOST structure.
- *     @portnum: IOC port number.
- *     @target: Physical ID of this target
- *
- *     Uses the ISR, but with special processing.
- *     MUST be single-threaded.
- *     Test will exit if target is at async & narrow.
- *
- *     Return: None.
- */
-static int
-mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
-{
-       MPT_ADAPTER             *ioc = hd->ioc;
-       VirtDevice              *pTarget;
-       SCSIDevicePage1_t       *pcfg1Data;
-       SCSIDevicePage0_t       *pcfg0Data;
-       u8                      *pbuf1;
-       u8                      *pbuf2;
-       u8                      *pDvBuf;
-       dma_addr_t               dvbuf_dma = -1;
-       dma_addr_t               buf1_dma = -1;
-       dma_addr_t               buf2_dma = -1;
-       dma_addr_t               cfg1_dma_addr = -1;
-       dma_addr_t               cfg0_dma_addr = -1;
-       ConfigPageHeader_t       header1;
-       ConfigPageHeader_t       header0;
-       DVPARAMETERS             dv;
-       INTERNAL_CMD             iocmd;
-       CONFIGPARMS              cfg;
-       int                      dv_alloc = 0;
-       int                      rc, sz = 0;
-       int                      bufsize = 0;
-       int                      dataBufSize = 0;
-       int                      echoBufSize = 0;
-       int                      notDone;
-       int                      patt;
-       int                      repeat;
-       int                      retcode = 0;
-       int                      nfactor =  MPT_ULTRA320;
-       char                     firstPass = 1;
-       char                     doFallback = 0;
-       char                     readPage0;
-       char                     bus, lun;
-       char                     inq0 = 0;
-
-       if (ioc->spi_data.sdp1length == 0)
-               return 0;
-
-       if (ioc->spi_data.sdp0length == 0)
-               return 0;
-
-       /* If multiple buses are used, require that the initiator
-        * id be the same on all buses.
-        */
-       if (id == ioc->pfacts[0].PortSCSIID)
-               return 0;
-
-       lun = 0;
-       bus = (u8) bus_number;
-       ddvtprintk((MYIOC_s_NOTE_FMT
-                       "DV started: bus=%d, id %d dv @ %p\n",
-                       ioc->name, bus, id, &dv));
-
-       /* Prep DV structure
-        */
-       memset (&dv, 0, sizeof(DVPARAMETERS));
-       dv.id = id;
-
-       /* Populate tmax with the current maximum
-        * transfer parameters for this target.
-        * Exit if narrow and async.
-        */
-       dv.cmd = MPT_GET_NVRAM_VALS;
-       mptscsih_dv_parms(hd, &dv, NULL);
-       if ((!dv.max.width) && (!dv.max.offset))
-               return 0;
-
-       /* Prep SCSI IO structure
-        */
-       iocmd.id = id;
-       iocmd.bus = bus;
-       iocmd.lun = lun;
-       iocmd.flags = 0;
-       iocmd.physDiskNum = -1;
-       iocmd.rsvd = iocmd.rsvd2 = 0;
-
-       pTarget = hd->Targets[id];
-       if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
-               /* Another GEM workaround. Check peripheral device type,
-                * if PROCESSOR, quit DV.
-                */
-               if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
-                       pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
-                       return 0;
-               }
-       }
-
-       /* Use tagged commands if possible.
-        */
-       if (pTarget) {
-               if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
-                       iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
-               else {
-                       if (hd->ioc->facts.FWVersion.Word < 0x01000600)
-                               return 0;
-
-                       if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
-                               (hd->ioc->facts.FWVersion.Word < 0x01010B00))
-                               return 0;
-               }
-       }
-
-       /* Prep cfg structure
-        */
-       cfg.pageAddr = (bus<<8) | id;
-       cfg.hdr = NULL;
-
-       /* Prep SDP0 header
-        */
-       header0.PageVersion = ioc->spi_data.sdp0version;
-       header0.PageLength = ioc->spi_data.sdp0length;
-       header0.PageNumber = 0;
-       header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-
-       /* Prep SDP1 header
-        */
-       header1.PageVersion = ioc->spi_data.sdp1version;
-       header1.PageLength = ioc->spi_data.sdp1length;
-       header1.PageNumber = 1;
-       header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-
-       if (header0.PageLength & 1)
-               dv_alloc = (header0.PageLength * 4) + 4;
-
-       dv_alloc +=  (2048 + (header1.PageLength * 4));
-
-       pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
-       if (pDvBuf == NULL)
-               return 0;
-
-       sz = 0;
-       pbuf1 = (u8 *)pDvBuf;
-       buf1_dma = dvbuf_dma;
-       sz +=1024;
-
-       pbuf2 = (u8 *) (pDvBuf + sz);
-       buf2_dma = dvbuf_dma + sz;
-       sz +=1024;
-
-       pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
-       cfg0_dma_addr = dvbuf_dma + sz;
-       sz += header0.PageLength * 4;
-
-       /* 8-byte alignment
-        */
-       if (header0.PageLength & 1)
-               sz += 4;
-
-       pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
-       cfg1_dma_addr = dvbuf_dma + sz;
-
-       /* Skip this ID? Set cfg.hdr to force config page write
-        */
-       {
-               ScsiCfgData *pspi_data = &hd->ioc->spi_data;
-               if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-                       /* Set the factor from nvram */
-                       nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
-                       if (nfactor < pspi_data->minSyncFactor )
-                               nfactor = pspi_data->minSyncFactor;
-
-                       if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
-                               (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
-
-                               ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
-                                       ioc->name, bus, id, lun));
-
-                               dv.cmd = MPT_SET_MAX;
-                               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-                               cfg.hdr = &header1;
-
-                               /* Save the final negotiated settings to
-                                * SCSI device page 1.
-                                */
-                               cfg.physAddr = cfg1_dma_addr;
-                               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-                               cfg.dir = 1;
-                               mpt_config(hd->ioc, &cfg);
-                               goto target_done;
-                       }
-               }
-       }
-
-       /* Finish iocmd inititialization - hidden or visible disk? */
-       if (ioc->spi_data.pIocPg3) {
-               /* Searc IOC page 3 for matching id
-                */
-               Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
-               int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
-
-               while (numPDisk) {
-                       if (pPDisk->PhysDiskID == id) {
-                               /* match */
-                               iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
-                               iocmd.physDiskNum = pPDisk->PhysDiskNum;
-
-                               /* Quiesce the IM
-                                */
-                               if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
-                                       ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
-                                       goto target_done;
-                               }
-                               break;
-                       }
-                       pPDisk++;
-                       numPDisk--;
-               }
-       }
-
-       /* RAID Volume ID's may double for a physical device. If RAID but
-        * not a physical ID as well, skip DV.
-        */
-       if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
-               goto target_done;
-
-
-       /* Basic Test.
-        * Async & Narrow - Inquiry
-        * Async & Narrow - Inquiry
-        * Maximum transfer rate - Inquiry
-        * Compare buffers:
-        *      If compare, test complete.
-        *      If miscompare and first pass, repeat
-        *      If miscompare and not first pass, fall back and repeat
-        */
-       hd->pLocal = NULL;
-       readPage0 = 0;
-       sz = SCSI_STD_INQUIRY_BYTES;
-       rc = MPT_SCANDV_GOOD;
-       while (1) {
-               ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
-               retcode = 0;
-               dv.cmd = MPT_SET_MIN;
-               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-               cfg.hdr = &header1;
-               cfg.physAddr = cfg1_dma_addr;
-               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-               cfg.dir = 1;
-               if (mpt_config(hd->ioc, &cfg) != 0)
-                       goto target_done;
-
-               /* Wide - narrow - wide workaround case
-                */
-               if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
-                       /* Send an untagged command to reset disk Qs corrupted
-                        * when a parity error occurs on a Request Sense.
-                        */
-                       if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
-                               ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
-                               (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
-
-                               iocmd.cmd = CMD_RequestSense;
-                               iocmd.data_dma = buf1_dma;
-                               iocmd.data = pbuf1;
-                               iocmd.size = 0x12;
-                               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                                       goto target_done;
-                               else {
-                                       if (hd->pLocal == NULL)
-                                               goto target_done;
-                                       rc = hd->pLocal->completion;
-                                       if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
-                                               dv.max.width = 0;
-                                               doFallback = 0;
-                                       } else
-                                               goto target_done;
-                               }
-                       } else
-                               goto target_done;
-               }
-
-               iocmd.cmd = CMD_Inquiry;
-               iocmd.data_dma = buf1_dma;
-               iocmd.data = pbuf1;
-               iocmd.size = sz;
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-               else {
-                       if (hd->pLocal == NULL)
-                               goto target_done;
-                       rc = hd->pLocal->completion;
-                       if (rc == MPT_SCANDV_GOOD) {
-                               if (hd->pLocal->scsiStatus == STS_BUSY) {
-                                       if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
-                                               retcode = 1;
-                                       else
-                                               retcode = 0;
-
-                                       goto target_done;
-                               }
-                       } else if  (rc == MPT_SCANDV_SENSE) {
-                               ;
-                       } else {
-                               /* If first command doesn't complete
-                                * with a good status or with a check condition,
-                                * exit.
-                                */
-                               goto target_done;
-                       }
-               }
-
-               /* Reset the size for disks
-                */
-               inq0 = (*pbuf1) & 0x1F;
-               if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
-                       sz = 0x40;
-                       iocmd.size = sz;
-               }
-
-               /* Another GEM workaround. Check peripheral device type,
-                * if PROCESSOR, quit DV.
-                */
-               if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08))
-                       goto target_done;
-
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-
-               if (sz == 0x40) {
-                       if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
-                               && (pTarget->minSyncFactor > 0x09)) {
-                               if ((pbuf1[56] & 0x04) == 0)
-                                       ;
-                               else if ((pbuf1[56] & 0x01) == 1) {
-                                       pTarget->minSyncFactor =
-                                           nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
-                               } else {
-                                       pTarget->minSyncFactor =
-                                           nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
-                               }
-
-                               dv.max.factor = pTarget->minSyncFactor;
-
-                               if ((pbuf1[56] & 0x02) == 0) {
-                                       pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-                                       hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
-                               }
-                       }
-               }
-
-               if (doFallback)
-                       dv.cmd = MPT_FALLBACK;
-               else
-                       dv.cmd = MPT_SET_MAX;
-
-               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-               if (mpt_config(hd->ioc, &cfg) != 0)
-                       goto target_done;
-
-               if ((!dv.now.width) && (!dv.now.offset))
-                       goto target_done;
-
-               iocmd.cmd = CMD_Inquiry;
-               iocmd.data_dma = buf2_dma;
-               iocmd.data = pbuf2;
-               iocmd.size = sz;
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-               else if (hd->pLocal == NULL)
-                       goto target_done;
-               else {
-                       /* Save the return code.
-                        * If this is the first pass,
-                        * read SCSI Device Page 0
-                        * and update the target max parameters.
-                        */
-                       rc = hd->pLocal->completion;
-                       doFallback = 0;
-                       if (rc == MPT_SCANDV_GOOD) {
-                               if (!readPage0) {
-                                       u32 sdp0_info;
-                                       u32 sdp0_nego;
-
-                                       cfg.hdr = &header0;
-                                       cfg.physAddr = cfg0_dma_addr;
-                                       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-                                       cfg.dir = 0;
-
-                                       if (mpt_config(hd->ioc, &cfg) != 0)
-                                               goto target_done;
-
-                                       sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
-                                       sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
-
-                                       /* Quantum and Fujitsu workarounds.
-                                        * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
-                                        * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
-                                        * Resetart with a request for U160.
-                                        */
-                                       if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
-                                                       doFallback = 1;
-                                       } else {
-                                               dv.cmd = MPT_UPDATE_MAX;
-                                               mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
-                                               /* Update the SCSI device page 1 area
-                                                */
-                                               pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
-                                               readPage0 = 1;
-                                       }
-                               }
-
-                               /* Quantum workaround. Restart this test will the fallback
-                                * flag set.
-                                */
-                               if (doFallback == 0) {
-                                       if (memcmp(pbuf1, pbuf2, sz) != 0) {
-                                               if (!firstPass)
-                                                       doFallback = 1;
-                                       } else
-                                               break;  /* test complete */
-                               }
-
-
-                       } else if (rc == MPT_SCANDV_ISSUE_SENSE)
-                               doFallback = 1; /* set fallback flag */
-                       else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE))
-                               doFallback = 1; /* set fallback flag */
-                       else
-                               goto target_done;
-
-                       firstPass = 0;
-               }
-       }
-       ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
-       inq0 = (*pbuf1) & 0x1F;
-
-       /* Continue only for disks
-        */
-       if (inq0 != 0)
-               goto target_done;
-
-       if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
-               goto target_done;
-
-       /* Start the Enhanced Test.
-        * 0) issue TUR to clear out check conditions
-        * 1) read capacity of echo (regular) buffer
-        * 2) reserve device
-        * 3) do write-read-compare data pattern test
-        * 4) release
-        * 5) update nego parms to target struct
-        */
-       cfg.hdr = &header1;
-       cfg.physAddr = cfg1_dma_addr;
-       cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-       cfg.dir = 1;
-
-       iocmd.cmd = CMD_TestUnitReady;
-       iocmd.data_dma = -1;
-       iocmd.data = NULL;
-       iocmd.size = 0;
-       notDone = 1;
-       while (notDone) {
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-
-               if (hd->pLocal == NULL)
-                       goto target_done;
-
-               rc = hd->pLocal->completion;
-               if (rc == MPT_SCANDV_GOOD)
-                       notDone = 0;
-               else if (rc == MPT_SCANDV_SENSE) {
-                       u8 skey = hd->pLocal->sense[2] & 0x0F;
-                       u8 asc = hd->pLocal->sense[12];
-                       u8 ascq = hd->pLocal->sense[13];
-                       ddvprintk((MYIOC_s_INFO_FMT
-                               "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
-                               ioc->name, skey, asc, ascq));
-
-                       if (skey == SK_UNIT_ATTENTION)
-                               notDone++; /* repeat */
-                       else if ((skey == SK_NOT_READY) &&
-                                       (asc == 0x04)&&(ascq == 0x01)) {
-                               /* wait then repeat */
-                               mdelay (2000);
-                               notDone++;
-                       } else if ((skey == SK_NOT_READY) && (asc == 0x3A)) {
-                               /* no medium, try read test anyway */
-                               notDone = 0;
-                       } else {
-                               /* All other errors are fatal.
-                                */
-                               ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
-                                               ioc->name));
-                               goto target_done;
-                       }
-               } else
-                       goto target_done;
-       }
-
-       iocmd.cmd = CMD_ReadBuffer;
-       iocmd.data_dma = buf1_dma;
-       iocmd.data = pbuf1;
-       iocmd.size = 4;
-       iocmd.flags |= MPT_ICFLAG_BUF_CAP;
-
-       dataBufSize = 0;
-       echoBufSize = 0;
-       for (patt = 0; patt < 2; patt++) {
-               if (patt == 0)
-                       iocmd.flags |= MPT_ICFLAG_ECHO;
-               else
-                       iocmd.flags &= ~MPT_ICFLAG_ECHO;
-
-               notDone = 1;
-               while (notDone) {
-                       bufsize = 0;
-
-                       /* If not ready after 8 trials,
-                        * give up on this device.
-                        */
-                       if (notDone > 8)
-                               goto target_done;
-
-                       if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                               goto target_done;
-                       else if (hd->pLocal == NULL)
-                               goto target_done;
-                       else {
-                               rc = hd->pLocal->completion;
-                               ddvprintk(("ReadBuffer Comp Code %d", rc));
-                               ddvprintk(("  buff: %0x %0x %0x %0x\n",
-                                       pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
-
-                               if (rc == MPT_SCANDV_GOOD) {
-                                       notDone = 0;
-                                       if (iocmd.flags & MPT_ICFLAG_ECHO) {
-                                               bufsize =  ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
-                                       } else {
-                                               bufsize =  pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
-                                       }
-                               } else if (rc == MPT_SCANDV_SENSE) {
-                                       u8 skey = hd->pLocal->sense[2] & 0x0F;
-                                       u8 asc = hd->pLocal->sense[12];
-                                       u8 ascq = hd->pLocal->sense[13];
-                                       ddvprintk((MYIOC_s_INFO_FMT
-                                               "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
-                                               ioc->name, skey, asc, ascq));
-                                       if (skey == SK_ILLEGAL_REQUEST) {
-                                               notDone = 0;
-                                       } else if (skey == SK_UNIT_ATTENTION) {
-                                               notDone++; /* repeat */
-                                       } else if ((skey == SK_NOT_READY) &&
-                                               (asc == 0x04)&&(ascq == 0x01)) {
-                                               /* wait then repeat */
-                                               mdelay (2000);
-                                               notDone++;
-                                       } else {
-                                               /* All other errors are fatal.
-                                                */
-                                               ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
-                                                       ioc->name));
-                                               goto target_done;
-                                       }
-                               } else {
-                                       /* All other errors are fatal
-                                        */
-                                       goto target_done;
-                               }
-                       }
-               }
-
-               if (iocmd.flags & MPT_ICFLAG_ECHO)
-                       echoBufSize = bufsize;
-               else
-                       dataBufSize = bufsize;
-       }
-       sz = 0;
-       iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
-
-       /* Use echo buffers if possible,
-        * Exit if both buffers are 0.
-        */
-       if (echoBufSize > 0) {
-               iocmd.flags |= MPT_ICFLAG_ECHO;
-               if (dataBufSize > 0)
-                       bufsize = min(echoBufSize, dataBufSize);
-               else
-                       bufsize = echoBufSize;
-       } else if (dataBufSize == 0)
-               goto target_done;
-
-       ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
-               (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
-
-       /* Data buffers for write-read-compare test max 1K.
-        */
-       sz = min(bufsize, 1024);
-
-       /* --- loop ----
-        * On first pass, always issue a reserve.
-        * On additional loops, only if a reset has occurred.
-        * iocmd.flags indicates if echo or regular buffer
-        */
-       for (patt = 0; patt < 4; patt++) {
-               ddvprintk(("Pattern %d\n", patt));
-               if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
-                       iocmd.cmd = CMD_TestUnitReady;
-                       iocmd.data_dma = -1;
-                       iocmd.data = NULL;
-                       iocmd.size = 0;
-                       if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                               goto target_done;
-
-                       iocmd.cmd = CMD_Release6;
-                       iocmd.data_dma = -1;
-                       iocmd.data = NULL;
-                       iocmd.size = 0;
-                       if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                               goto target_done;
-                       else if (hd->pLocal == NULL)
-                               goto target_done;
-                       else {
-                               rc = hd->pLocal->completion;
-                               ddvprintk(("Release rc %d\n", rc));
-                               if (rc == MPT_SCANDV_GOOD)
-                                       iocmd.flags &= ~MPT_ICFLAG_RESERVED;
-                               else
-                                       goto target_done;
-                       }
-                       iocmd.flags &= ~MPT_ICFLAG_RESERVED;
-               }
-               iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
-
-               repeat = 5;
-               while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
-                       iocmd.cmd = CMD_Reserve6;
-                       iocmd.data_dma = -1;
-                       iocmd.data = NULL;
-                       iocmd.size = 0;
-                       if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                               goto target_done;
-                       else if (hd->pLocal == NULL)
-                               goto target_done;
-                       else {
-                               rc = hd->pLocal->completion;
-                               if (rc == MPT_SCANDV_GOOD) {
-                                       iocmd.flags |= MPT_ICFLAG_RESERVED;
-                               } else if (rc == MPT_SCANDV_SENSE) {
-                                       /* Wait if coming ready
-                                        */
-                                       u8 skey = hd->pLocal->sense[2] & 0x0F;
-                                       u8 asc = hd->pLocal->sense[12];
-                                       u8 ascq = hd->pLocal->sense[13];
-                                       ddvprintk((MYIOC_s_INFO_FMT
-                                               "DV: Reserve Failed: ", ioc->name));
-                                       ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
-                                                       skey, asc, ascq));
-
-                                       if ((skey == SK_NOT_READY) && (asc == 0x04)&&
-                                                                       (ascq == 0x01)) {
-                                               /* wait then repeat */
-                                               mdelay (2000);
-                                               notDone++;
-                                       } else {
-                                               ddvprintk((MYIOC_s_INFO_FMT
-                                                       "DV: Reserved Failed.", ioc->name));
-                                               goto target_done;
-                                       }
-                               } else {
-                                       ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
-                                                        ioc->name));
-                                       goto target_done;
-                               }
-                       }
-               }
-
-               mptscsih_fillbuf(pbuf1, sz, patt, 1);
-               iocmd.cmd = CMD_WriteBuffer;
-               iocmd.data_dma = buf1_dma;
-               iocmd.data = pbuf1;
-               iocmd.size = sz;
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-               else if (hd->pLocal == NULL)
-                       goto target_done;
-               else {
-                       rc = hd->pLocal->completion;
-                       if (rc == MPT_SCANDV_GOOD)
-                               ;               /* Issue read buffer */
-                       else if (rc == MPT_SCANDV_DID_RESET) {
-                               /* If using echo buffers, reset to data buffers.
-                                * Else do Fallback and restart
-                                * this test (re-issue reserve
-                                * because of bus reset).
-                                */
-                               if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
-                                       iocmd.flags &= ~MPT_ICFLAG_ECHO;
-                               } else {
-                                       dv.cmd = MPT_FALLBACK;
-                                       mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-                                       if (mpt_config(hd->ioc, &cfg) != 0)
-                                               goto target_done;
-
-                                       if ((!dv.now.width) && (!dv.now.offset))
-                                               goto target_done;
-                               }
-
-                               iocmd.flags |= MPT_ICFLAG_DID_RESET;
-                               patt = -1;
-                               continue;
-                       } else if (rc == MPT_SCANDV_SENSE) {
-                               /* Restart data test if UA, else quit.
-                                */
-                               u8 skey = hd->pLocal->sense[2] & 0x0F;
-                               ddvprintk((MYIOC_s_INFO_FMT
-                                       "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
-                                       hd->pLocal->sense[12], hd->pLocal->sense[13]));
-                               if (skey == SK_UNIT_ATTENTION) {
-                                       patt = -1;
-                                       continue;
-                               } else if (skey == SK_ILLEGAL_REQUEST) {
-                                       if (iocmd.flags & MPT_ICFLAG_ECHO) {
-                                               if (dataBufSize >= bufsize) {
-                                                       iocmd.flags &= ~MPT_ICFLAG_ECHO;
-                                                       patt = -1;
-                                                       continue;
-                                               }
-                                       }
-                                       goto target_done;
-                               }
-                               else
-                                       goto target_done;
-                       } else {
-                               /* fatal error */
-                               goto target_done;
-                       }
-               }
-
-               iocmd.cmd = CMD_ReadBuffer;
-               iocmd.data_dma = buf2_dma;
-               iocmd.data = pbuf2;
-               iocmd.size = sz;
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       goto target_done;
-               else if (hd->pLocal == NULL)
-                       goto target_done;
-               else {
-                       rc = hd->pLocal->completion;
-                       if (rc == MPT_SCANDV_GOOD) {
-                                /* If buffers compare,
-                                 * go to next pattern,
-                                 * else, do a fallback and restart
-                                 * data transfer test.
-                                 */
-                               if (memcmp (pbuf1, pbuf2, sz) == 0) {
-                                       ; /* goto next pattern */
-                               } else {
-                                       /* Miscompare with Echo buffer, go to data buffer,
-                                        * if that buffer exists.
-                                        * Miscompare with Data buffer, check first 4 bytes,
-                                        * some devices return capacity. Exit in this case.
-                                        */
-                                       if (iocmd.flags & MPT_ICFLAG_ECHO) {
-                                               if (dataBufSize >= bufsize)
-                                                       iocmd.flags &= ~MPT_ICFLAG_ECHO;
-                                               else
-                                                       goto target_done;
-                                       } else {
-                                               if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
-                                                       /* Argh. Device returning wrong data.
-                                                        * Quit DV for this device.
-                                                        */
-                                                       goto target_done;
-                                               }
-
-                                               /* Had an actual miscompare. Slow down.*/
-                                               dv.cmd = MPT_FALLBACK;
-                                               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-                                               if (mpt_config(hd->ioc, &cfg) != 0)
-                                                       goto target_done;
-
-                                               if ((!dv.now.width) && (!dv.now.offset))
-                                                       goto target_done;
-                                       }
-
-                                       patt = -1;
-                                       continue;
-                               }
-                       } else if (rc == MPT_SCANDV_DID_RESET) {
-                               /* Do Fallback and restart
-                                * this test (re-issue reserve
-                                * because of bus reset).
-                                */
-                               dv.cmd = MPT_FALLBACK;
-                               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-                               if (mpt_config(hd->ioc, &cfg) != 0)
-                                        goto target_done;
-
-                               if ((!dv.now.width) && (!dv.now.offset))
-                                       goto target_done;
-
-                               iocmd.flags |= MPT_ICFLAG_DID_RESET;
-                               patt = -1;
-                               continue;
-                       } else if (rc == MPT_SCANDV_SENSE) {
-                               /* Restart data test if UA, else quit.
-                                */
-                               u8 skey = hd->pLocal->sense[2] & 0x0F;
-                               ddvprintk((MYIOC_s_INFO_FMT
-                                       "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
-                                       hd->pLocal->sense[12], hd->pLocal->sense[13]));
-                               if (skey == SK_UNIT_ATTENTION) {
-                                       patt = -1;
-                                       continue;
-                               }
-                               else
-                                       goto target_done;
-                       } else {
-                               /* fatal error */
-                               goto target_done;
-                       }
-               }
-
-       } /* --- end of patt loop ---- */
-
-target_done:
-       if (iocmd.flags & MPT_ICFLAG_RESERVED) {
-               iocmd.cmd = CMD_Release6;
-               iocmd.data_dma = -1;
-               iocmd.data = NULL;
-               iocmd.size = 0;
-               if (mptscsih_do_cmd(hd, &iocmd) < 0)
-                       printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
-                                       ioc->name, id);
-               else if (hd->pLocal) {
-                       if (hd->pLocal->completion == MPT_SCANDV_GOOD)
-                               iocmd.flags &= ~MPT_ICFLAG_RESERVED;
-               } else {
-                       printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
-                                               ioc->name, id);
-               }
-       }
-
-
-       /* Set if cfg1_dma_addr contents is valid
-        */
-       if ((cfg.hdr != NULL) && (retcode == 0)){
-               /* If disk, not U320, disable QAS
-                */
-               if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320))
-                       hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
-
-               dv.cmd = MPT_SAVE;
-               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
-               /* Double writes to SDP1 can cause problems,
-                * skip save of the final negotiated settings to
-                * SCSI device page 1.
-                *
-               cfg.hdr = &header1;
-               cfg.physAddr = cfg1_dma_addr;
-               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-               cfg.dir = 1;
-               mpt_config(hd->ioc, &cfg);
-                */
-       }
-
-       /* If this is a RAID Passthrough, enable internal IOs
-        */
-       if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
-               if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
-                       ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
-       }
-
-       /* Done with the DV scan of the current target
-        */
-       if (pDvBuf)
-               pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
-
-       ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n",
-                       ioc->name));
-
-       return retcode;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_dv_parms - perform a variety of operations on the
- *     parameters used for negotiation.
- *     @hd: Pointer to a SCSI host.
- *     @dv: Pointer to a structure that contains the maximum and current
- *             negotiated parameters.
- */
-static void
-mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
-{
-       VirtDevice              *pTarget;
-       SCSIDevicePage0_t       *pPage0;
-       SCSIDevicePage1_t       *pPage1;
-       int                     val = 0, data, configuration;
-       u8                      width = 0;
-       u8                      offset = 0;
-       u8                      factor = 0;
-       u8                      negoFlags = 0;
-       u8                      cmd = dv->cmd;
-       u8                      id = dv->id;
-
-       switch (cmd) {
-       case MPT_GET_NVRAM_VALS:
-               ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
-                                                        hd->ioc->name));
-               /* Get the NVRAM values and save in tmax
-                * If not an LVD bus, the adapter minSyncFactor has been
-                * already throttled back.
-                */
-               if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
-                       width = pTarget->maxWidth;
-                       offset = pTarget->maxOffset;
-                       factor = pTarget->minSyncFactor;
-                       negoFlags = pTarget->negoFlags;
-               } else {
-                       if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-                               data = hd->ioc->spi_data.nvram[id];
-                               width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
-                               if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
-                                       factor = MPT_ASYNC;
-                               else {
-                                       factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
-                                       if ((factor == 0) || (factor == MPT_ASYNC)){
-                                               factor = MPT_ASYNC;
-                                               offset = 0;
-                                       }
-                               }
-                       } else {
-                               width = MPT_NARROW;
-                               offset = 0;
-                               factor = MPT_ASYNC;
-                       }
-
-                       /* Set the negotiation flags */
-                       negoFlags = hd->ioc->spi_data.noQas;
-                       if (!width)
-                               negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
-                       if (!offset)
-                               negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
-               }
-
-               /* limit by adapter capabilities */
-               width = min(width, hd->ioc->spi_data.maxBusWidth);
-               offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
-               factor = max(factor, hd->ioc->spi_data.minSyncFactor);
-
-               /* Check Consistency */
-               if (offset && (factor < MPT_ULTRA2) && !width)
-                       factor = MPT_ULTRA2;
-
-               dv->max.width = width;
-               dv->max.offset = offset;
-               dv->max.factor = factor;
-               dv->max.flags = negoFlags;
-               ddvprintk((" width %d, factor %x, offset %x flags %x\n",
-                               width, factor, offset, negoFlags));
-               break;
-
-       case MPT_UPDATE_MAX:
-               ddvprintk((MYIOC_s_NOTE_FMT
-                       "Updating with SDP0 Data: ", hd->ioc->name));
-               /* Update tmax values with those from Device Page 0.*/
-               pPage0 = (SCSIDevicePage0_t *) pPage;
-               if (pPage0) {
-                       val = cpu_to_le32(pPage0->NegotiatedParameters);
-                       dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
-                       dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
-                       dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
-               }
-
-               dv->now.width = dv->max.width;
-               dv->now.offset = dv->max.offset;
-               dv->now.factor = dv->max.factor;
-               ddvprintk(("width %d, factor %x, offset %x, flags %x\n",
-                               dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
-               break;
-
-       case MPT_SET_MAX:
-               ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
-                                                               hd->ioc->name));
-               /* Set current to the max values. Update the config page.*/
-               dv->now.width = dv->max.width;
-               dv->now.offset = dv->max.offset;
-               dv->now.factor = dv->max.factor;
-               dv->now.flags = dv->max.flags;
-
-               pPage1 = (SCSIDevicePage1_t *)pPage;
-               if (pPage1) {
-                       mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
-                               dv->now.offset, &val, &configuration, dv->now.flags);
-                       pPage1->RequestedParameters = le32_to_cpu(val);
-                       pPage1->Reserved = 0;
-                       pPage1->Configuration = le32_to_cpu(configuration);
-
-               }
-
-               ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n",
-                               dv->now.width, dv->now.factor, dv->now.offset, val, configuration));
-               break;
-
-       case MPT_SET_MIN:
-               ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
-                                                               hd->ioc->name));
-               /* Set page to asynchronous and narrow
-                * Do not update now, breaks fallback routine. */
-               width = MPT_NARROW;
-               offset = 0;
-               factor = MPT_ASYNC;
-               negoFlags = dv->max.flags;
-
-               pPage1 = (SCSIDevicePage1_t *)pPage;
-               if (pPage1) {
-                       mptscsih_setDevicePage1Flags (width, factor,
-                               offset, &val, &configuration, negoFlags);
-                       pPage1->RequestedParameters = le32_to_cpu(val);
-                       pPage1->Reserved = 0;
-                       pPage1->Configuration = le32_to_cpu(configuration);
-               }
-               ddvprintk(("width %d, factor %x, offset %x request %x config %x\n",
-                               width, factor, offset, val, configuration));
-               break;
-
-       case MPT_FALLBACK:
-               ddvprintk((MYIOC_s_NOTE_FMT
-                       "Fallback: Start: offset %d, factor %x, width %d \n",
-                               hd->ioc->name, dv->now.offset,
-                               dv->now.factor, dv->now.width));
-               width = dv->now.width;
-               offset = dv->now.offset;
-               factor = dv->now.factor;
-               if ((offset) && (dv->max.width)) {
-                       if (factor < MPT_ULTRA160)
-                               factor = MPT_ULTRA160;
-                       else if (factor < MPT_ULTRA2) {
-                               factor = MPT_ULTRA2;
-                               width = MPT_WIDE;
-                       } else if ((factor == MPT_ULTRA2) && width) {
-                               factor = MPT_ULTRA2;
-                               width = MPT_NARROW;
-                       } else if (factor < MPT_ULTRA) {
-                               factor = MPT_ULTRA;
-                               width = MPT_WIDE;
-                       } else if ((factor == MPT_ULTRA) && width) {
-                               width = MPT_NARROW;
-                       } else if (factor < MPT_FAST) {
-                               factor = MPT_FAST;
-                               width = MPT_WIDE;
-                       } else if ((factor == MPT_FAST) && width) {
-                               factor = MPT_FAST;
-                               width = MPT_NARROW;
-                       } else if (factor < MPT_SCSI) {
-                               factor = MPT_SCSI;
-                               width = MPT_WIDE;
-                       } else if ((factor == MPT_SCSI) && width) {
-                               factor = MPT_SCSI;
-                               width = MPT_NARROW;
-                       } else {
-                               factor = MPT_ASYNC;
-                               offset = 0;
-                       }
-
-               } else if (offset) {
-                       width = MPT_NARROW;
-                       if (factor < MPT_ULTRA)
-                               factor = MPT_ULTRA;
-                       else if (factor < MPT_FAST)
-                               factor = MPT_FAST;
-                       else if (factor < MPT_SCSI)
-                               factor = MPT_SCSI;
-                       else {
-                               factor = MPT_ASYNC;
-                               offset = 0;
-                       }
-
-               } else {
-                       width = MPT_NARROW;
-                       factor = MPT_ASYNC;
-               }
-               dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
-
-               dv->now.width = width;
-               dv->now.offset = offset;
-               dv->now.factor = factor;
-               dv->now.flags = dv->max.flags;
-
-               pPage1 = (SCSIDevicePage1_t *)pPage;
-               if (pPage1) {
-                       mptscsih_setDevicePage1Flags (width, factor, offset, &val,
-                                               &configuration, dv->now.flags);
-
-                       pPage1->RequestedParameters = le32_to_cpu(val);
-                       pPage1->Reserved = 0;
-                       pPage1->Configuration = le32_to_cpu(configuration);
-               }
-
-               ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n",
-                            dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
-               break;
-
-       case MPT_SAVE:
-               ddvprintk((MYIOC_s_NOTE_FMT
-                       "Saving to Target structure: ", hd->ioc->name));
-               ddvprintk(("offset %d, factor %x, width %d \n",
-                            dv->now.offset, dv->now.factor, dv->now.width));
-
-               /* Save these values to target structures
-                * or overwrite nvram (phys disks only).
-                */
-
-               if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
-                       pTarget->maxWidth = dv->now.width;
-                       pTarget->maxOffset = dv->now.offset;
-                       pTarget->minSyncFactor = dv->now.factor;
-                       pTarget->negoFlags = dv->now.flags;
-               } else {
-                       /* Preserv all flags, use
-                        * read-modify-write algorithm
-                        */
-                       if (hd->ioc->spi_data.nvram) {
-                               data = hd->ioc->spi_data.nvram[id];
-
-                               if (dv->now.width)
-                                       data &= ~MPT_NVRAM_WIDE_DISABLE;
-                               else
-                                       data |= MPT_NVRAM_WIDE_DISABLE;
-
-                               if (!dv->now.offset)
-                                       factor = MPT_ASYNC;
-
-                               data &= ~MPT_NVRAM_SYNC_MASK;
-                               data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
-
-                               hd->ioc->spi_data.nvram[id] = data;
-                       }
-               }
-               break;
-       }
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_fillbuf - fill a buffer with a special data pattern
- *             cleanup. For bus scan only.
- *
- *     @buffer: Pointer to data buffer to be filled.
- *     @size: Number of bytes to fill
- *     @index: Pattern index
- *     @width: bus width, 0 (8 bits) or 1 (16 bits)
- */
-static void
-mptscsih_fillbuf(char *buffer, int size, int index, int width)
-{
-       char *ptr = buffer;
-       int ii;
-       char byte;
-       short val;
-
-       switch (index) {
-       case 0:
-
-               if (width) {
-                       /* Pattern:  0000 FFFF 0000 FFFF
-                        */
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               if (ii & 0x02)
-                                       *ptr = 0xFF;
-                               else
-                                       *ptr = 0x00;
-                       }
-               } else {
-                       /* Pattern:  00 FF 00 FF
-                        */
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               if (ii & 0x01)
-                                       *ptr = 0xFF;
-                               else
-                                       *ptr = 0x00;
-                       }
-               }
-               break;
-
-       case 1:
-               if (width) {
-                       /* Pattern:  5555 AAAA 5555 AAAA 5555
-                        */
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               if (ii & 0x02)
-                                       *ptr = 0xAA;
-                               else
-                                       *ptr = 0x55;
-                       }
-               } else {
-                       /* Pattern:  55 AA 55 AA 55
-                        */
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               if (ii & 0x01)
-                                       *ptr = 0xAA;
-                               else
-                                       *ptr = 0x55;
-                       }
-               }
-               break;
-
-       case 2:
-               /* Pattern:  00 01 02 03 04 05
-                * ... FE FF 00 01..
-                */
-               for (ii=0; ii < size; ii++, ptr++)
-                       *ptr = (char) ii;
-               break;
-
-       case 3:
-               if (width) {
-                       /* Wide Pattern:  FFFE 0001 FFFD 0002
-                        * ...  4000 DFFF 8000 EFFF
-                        */
-                       byte = 0;
-                       for (ii=0; ii < size/2; ii++) {
-                               /* Create the base pattern
-                                */
-                               val = (1 << byte);
-                               /* every 64 (0x40) bytes flip the pattern
-                                * since we fill 2 bytes / iteration,
-                                * test for ii = 0x20
-                                */
-                               if (ii & 0x20)
-                                       val = ~(val);
-
-                               if (ii & 0x01) {
-                                       *ptr = (char)( (val & 0xFF00) >> 8);
-                                       ptr++;
-                                       *ptr = (char)(val & 0xFF);
-                                       byte++;
-                                       byte &= 0x0F;
-                               } else {
-                                       val = ~val;
-                                       *ptr = (char)( (val & 0xFF00) >> 8);
-                                       ptr++;
-                                       *ptr = (char)(val & 0xFF);
-                               }
-
-                               ptr++;
-                       }
-               } else {
-                       /* Narrow Pattern:  FE 01 FD 02 FB 04
-                        * .. 7F 80 01 FE 02 FD ...  80 7F
-                        */
-                       byte = 0;
-                       for (ii=0; ii < size; ii++, ptr++) {
-                               /* Base pattern - first 32 bytes
-                                */
-                               if (ii & 0x01) {
-                                       *ptr = (1 << byte);
-                                       byte++;
-                                       byte &= 0x07;
-                               } else {
-                                       *ptr = (char) (~(1 << byte));
-                               }
-
-                               /* Flip the pattern every 32 bytes
-                                */
-                               if (ii & 0x20)
-                                       *ptr = ~(*ptr);
-                       }
-               }
-               break;
-       }
-}
-#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Commandline Parsing routines and defines.
- *
- * insmod format:
- *     insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1"
- *  boot format:
- *     mptscsih=width:1,dv:n,factor:0x8,saf-te:1
- *
- */
-#ifdef MODULE
-#define        ARG_SEP ' '
-#else
-#define        ARG_SEP ','
-#endif
-
-#ifdef MODULE
-static char setup_token[] __initdata =
-       "dv:"
-       "width:"
-       "factor:"
-       "saf-te:"
-       ;       /* DO NOT REMOVE THIS ';' */
-#endif
-       
-#define OPT_DV                 1
-#define OPT_MAX_WIDTH          2
-#define OPT_MIN_SYNC_FACTOR    3
-#define OPT_SAF_TE             4
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#ifdef MODULE
-static int
-get_setup_token(char *p)
-{
-       char *cur = setup_token;
-       char *pc;
-       int i = 0;
-
-       while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
-               ++pc;
-               ++i;
-               if (!strncmp(p, cur, pc - cur))
-                       return i;
-               cur = pc;
-       }
-       return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
-mptscsih_setup(char *str)
-{
-       char *cur = str;
-       char *pc, *pv;
-       unsigned long val;
-       int  c;
-
-       while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
-               char *pe;
-
-               val = 0;
-               pv = pc;
-               c = *++pv;
-
-               if      (c == 'n')
-                       val = 0;
-               else if (c == 'y')
-                       val = 1;
-               else
-                       val = (int) simple_strtoul(pv, &pe, 0);
-
-               printk("Found Token: %s, value %x\n", cur, (int)val);
-               switch (get_setup_token(cur)) {
-               case OPT_DV:
-                       driver_setup.dv = val;
-                       break;
-
-               case OPT_MAX_WIDTH:
-                       driver_setup.max_width = val;
-                       break;
-
-               case OPT_MIN_SYNC_FACTOR:
-                       driver_setup.min_sync_fac = val;
-                       break;
-
-               case OPT_SAF_TE:
-                       driver_setup.saf_te = val;
-                       break;
-
-               default:
-                       printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
-                       break;
-               }
-
-               if ((cur = strchr(cur, ARG_SEP)) != NULL)
-                       ++cur;
-       }
-       return 1;
-}
-#endif
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-
-module_init(mptscsih_init);
-module_exit(mptscsih_exit);