fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / message / fusion / mptctl.c
index 40379f9..504632d 100644 (file)
@@ -1,40 +1,12 @@
 /*
  *  linux/drivers/message/fusion/mptctl.c
- *      Fusion MPT misc device (ioctl) driver.
- *      For use with PCI chip/adapter(s):
- *          LSIFC9xx/LSI409xx Fibre Channel
+ *      mpt Ioctl driver.
+ *      For use with LSI Logic PCI chip/adapters
  *      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!
- *
- *      A big THANKS to Eddie C. Dost for fixing the ioctl path
- *      and most importantly f/w download on sparc64 platform!
- *      (plus Eddie's other helpful hints and insights)
- *
- *      Thanks to Arnaldo Carvalho de Melo for finding and patching
- *      a potential memory leak in mptctl_do_fw_download(),
- *      and for some kmalloc insight:-)
- *
- *      (see also mptbase.c)
- *
- *  Copyright (c) 1999-2004 LSI Logic Corporation
- *  Originally By: Steven J. Ralston, Noah Romer
- *  (mailto:sjralston1@netscape.net)
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
- *  $Id: mptctl.c,v 1.63 2002/12/03 21:26:33 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -73,7 +45,6 @@
 */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/delay.h>       /* for mdelay */
 #include <linux/miscdevice.h>
 #include <linux/smp_lock.h>
+#include <linux/compat.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#include <linux/kdev_t.h>      /* needed for access to Scsi_Host struct */
-#include <linux/blkdev.h>
-#include "../../scsi/scsi.h"
-#include "../../scsi/hosts.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>
 
-#define COPYRIGHT      "Copyright (c) 1999-2004 LSI Logic Corporation"
-#define MODULEAUTHOR   "Steven J. Ralston, Noah Romer, Pamela Delaney"
+#define COPYRIGHT      "Copyright (c) 1999-2007 LSI Logic Corporation"
+#define MODULEAUTHOR   "LSI Logic Corporation"
 #include "mptbase.h"
 #include "mptctl.h"
 
 #define my_VERSION     MPT_LINUX_VERSION_COMMON
 #define MYNAM          "mptctl"
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,62)
-EXPORT_NO_SYMBOLS;
-#endif
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 static int mptctl_id = -1;
-static struct semaphore mptctl_syscall_sem_ioc[MPT_MAX_ADAPTERS];
 
 static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
 
@@ -128,29 +99,35 @@ struct buflist {
  * arg contents specific to function.
  */
 static int mptctl_fw_download(unsigned long arg);
-static int mptctl_getiocinfo (unsigned long arg, unsigned int cmd);
-static int mptctl_gettargetinfo (unsigned long arg);
-static int mptctl_readtest (unsigned long arg);
-static int mptctl_mpt_command (unsigned long arg);
-static int mptctl_eventquery (unsigned long arg);
-static int mptctl_eventenable (unsigned long arg);
-static int mptctl_eventreport (unsigned long arg);
-static int mptctl_replace_fw (unsigned long arg);
+static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
+static int mptctl_gettargetinfo(unsigned long arg);
+static int mptctl_readtest(unsigned long arg);
+static int mptctl_mpt_command(unsigned long arg);
+static int mptctl_eventquery(unsigned long arg);
+static int mptctl_eventenable(unsigned long arg);
+static int mptctl_eventreport(unsigned long arg);
+static int mptctl_replace_fw(unsigned long arg);
 
 static int mptctl_do_reset(unsigned long arg);
 static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
 static int mptctl_hp_targetinfo(unsigned long arg);
 
+static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
+static void mptctl_remove(struct pci_dev *);
+
+#ifdef CONFIG_COMPAT
+static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+#endif
 /*
  * Private function calls.
  */
-static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local);
-static int mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen);
-static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frags,
+static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
+static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
+static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
                struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
-static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
+static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
                struct buflist *buflist, MPT_ADAPTER *ioc);
-static void mptctl_timer_expired (unsigned long data);
+static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
 static int  mptctl_bus_reset(MPT_IOCTL *ioctl);
 static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd);
 static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
@@ -160,6 +137,12 @@ static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
  */
 static int  mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
 
+/*
+ * Event Handler function
+ */
+static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+static struct fasync_struct *async_queue=NULL;
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  * Scatter gather list (SGL) sizes and limits...
@@ -183,9 +166,6 @@ static int  mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
 
 #define MPT_IOCTL_DEFAULT_TIMEOUT 10   /* Default timeout value (seconds) */
 
-static u32 fwReplyBuffer[16];
-static pMPIDefaultReply_t ReplyMsg = NULL;
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptctl_syscall_down - Down the MPT adapter syscall semaphore.
@@ -203,16 +183,11 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
        int rc = 0;
        dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
 
-       if (ioc->ioctl->tmPtr != NULL) {
-               dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down BUSY\n"));
-               return -EBUSY;
-       }
-
        if (nonblock) {
-               if (down_trylock(&mptctl_syscall_sem_ioc[ioc->id]))
+               if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
                        rc = -EAGAIN;
        } else {
-               if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id]))
+               if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
                        rc = -ERESTARTSYS;
        }
        dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -234,131 +209,101 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
        u16 iocStatus;
        u8 cmd;
 
-       dctlprintk((MYIOC_s_INFO_FMT ": mptctl_reply()!\n", ioc->name));
+       dctlprintk(("mptctl_reply()!\n"));
        if (req)
                 cmd = req->u.hdr.Function;
        else
                return 1;
 
        if (ioc->ioctl) {
-               /* If timer is not running, then an error occurred.
-                * A timeout will call the reset routine to reload the messaging
-                * queues.
-                * Main callback will free message and reply frames.
-                */
-               if (reply && (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) &&
-                   (ioc->ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)) {
-                       /* This is internally generated TM
-                        */
-                       del_timer (&ioc->ioctl->TMtimer);
-                       ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
-
-                       mptctl_free_tm_flags(ioc);
 
-                       /* If TM failed, reset the timer on the existing command,
-                        * will trigger an adapter reset.
-                        */
-                       iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
-                       if (iocStatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED) {
-                               if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) {
-                                       ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
-                                       del_timer (&ioc->ioctl->timer);
-                                       ioc->ioctl->timer.expires = jiffies + HZ;
-                                       add_timer(&ioc->ioctl->timer);
-                               }
-                       }
-                       ioc->ioctl->tmPtr = NULL;
+               if (reply==NULL) {
 
-               } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) {
-                       /* Delete this timer
-                        */
-                       del_timer (&ioc->ioctl->timer);
-                       ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
+                       dctlprintk(("mptctl_reply() NULL Reply "
+                               "Function=%x!\n", cmd));
 
-                       /* Set the overall status byte.  Good if:
-                        * IOC status is good OR if no reply and a SCSI IO request
-                        */
-                       if (reply) {
-                               /* Copy the reply frame (which much exist
-                                * for non-SCSI I/O) to the IOC structure.
-                                */
-                               dctlprintk((MYIOC_s_INFO_FMT ": Copying Reply Frame @%p to IOC!\n",
-                                               ioc->name, reply));
-                               memcpy(ioc->ioctl->ReplyFrame, reply,
-                                       min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
-                               ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
-
-                               /* Set the command status to GOOD if IOC Status is GOOD
-                                * OR if SCSI I/O cmd and data underrun or recovered error.
-                                */
-                               iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
-                               if (iocStatus  == MPI_IOCSTATUS_SUCCESS)
-                                       ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
+                       ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
+                       ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
 
-                               if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
-                                       (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
-                                       ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
+                       /* We are done, issue wake up
+                       */
+                       ioc->ioctl->wait_done = 1;
+                       wake_up (&mptctl_wait);
+                       return 1;
 
-                                       if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
-                                               (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
-                                               ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
-                                       }
-                               }
+               }
 
-                               /* Copy the sense data - if present
-                                */
-                               if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
-                                       (reply->u.sreply.SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)){
-
-                                       sz = req->u.scsireq.SenseBufferLength;
-                                       req_index = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
-                                       sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
-                                       memcpy(ioc->ioctl->sense, sense_data, sz);
-                                       ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
-                               }
+               dctlprintk(("mptctl_reply() with req=%p "
+                       "reply=%p Function=%x!\n", req, reply, cmd));
 
-                               if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
-                                       mptctl_free_tm_flags(ioc);
+               /* Copy the reply frame (which much exist
+                * for non-SCSI I/O) to the IOC structure.
+                */
+               dctlprintk(("Copying Reply Frame @%p to ioc%d!\n",
+                       reply, ioc->id));
+               memcpy(ioc->ioctl->ReplyFrame, reply,
+                       min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
+               ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
+
+               /* Set the command status to GOOD if IOC Status is GOOD
+                * OR if SCSI I/O cmd and data underrun or recovered error.
+                */
+               iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK;
+               if (iocStatus  == MPI_IOCSTATUS_SUCCESS)
+                       ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
 
+               if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
+                       (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+                       ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
 
-                       } else if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
-                                       (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
-                               ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
-                               ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
+                       if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
+                       (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
+                       ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
                        }
+               }
 
-                       /* We are done, issue wake up
-                        */
-                       ioc->ioctl->wait_done = 1;
-                       wake_up (&mptctl_wait);
-               } else if (reply && cmd == MPI_FUNCTION_FW_DOWNLOAD) {
-                       /* Two paths to FW DOWNLOAD! */
-                       // NOTE: Expects/requires non-Turbo reply!
-                       dctlprintk((MYIOC_s_INFO_FMT ":Caching MPI_FUNCTION_FW_DOWNLOAD reply!\n",
-                               ioc->name));
-                       memcpy(fwReplyBuffer, reply, min_t(int, sizeof(fwReplyBuffer), 4*reply->u.reply.MsgLength));
-                       ReplyMsg = (pMPIDefaultReply_t) fwReplyBuffer;
+               /* Copy the sense data - if present
+                */
+               if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
+                       (reply->u.sreply.SCSIState &
+                        MPI_SCSI_STATE_AUTOSENSE_VALID)){
+                       sz = req->u.scsireq.SenseBufferLength;
+                       req_index =
+                           le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
+                       sense_data =
+                           ((u8 *)ioc->sense_buf_pool +
+                            (req_index * MPT_SENSE_BUFFER_ALLOC));
+                       memcpy(ioc->ioctl->sense, sense_data, sz);
+                       ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
                }
+
+               if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
+                       mptctl_free_tm_flags(ioc);
+
+               /* We are done, issue wake up
+                */
+               ioc->ioctl->wait_done = 1;
+               wake_up (&mptctl_wait);
        }
        return 1;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_timer_expired
+/* mptctl_timeout_expired
  *
- * Call back for timer process. Used only for ioctl functionality.
+ * Expecting an interrupt, however timed out.
  *
  */
-static void mptctl_timer_expired (unsigned long data)
+static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
 {
-       MPT_IOCTL *ioctl = (MPT_IOCTL *) data;
        int rc = 1;
 
-       dctlprintk((KERN_NOTICE MYNAM ": Timer Expired! Host %d\n",
+       dctlprintk((KERN_NOTICE MYNAM ": Timeout Expired! Host %d\n",
                                ioctl->ioc->id));
        if (ioctl == NULL)
                return;
 
+       ioctl->wait_done = 0;
        if (ioctl->reset & MPTCTL_RESET_OK)
                rc = mptctl_bus_reset(ioctl);
 
@@ -366,6 +311,8 @@ static void mptctl_timer_expired (unsigned long data)
                /* Issue a reset for this device.
                 * The IOC is not responding.
                 */
+               dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
+                        ioctl->ioc->name));
                mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
        }
        return;
@@ -390,7 +337,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
 
        if (ioctl->ioc->sh == NULL)
                return -EPERM;
-       
+
        hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata;
        if (hd == NULL)
                return -EPERM;
@@ -402,7 +349,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
 
        /* Send request
         */
-       if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc->id)) == NULL) {
+       if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc)) == NULL) {
                dctlprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
                                ioctl->ioc->name));
 
@@ -430,26 +377,34 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
                pScsiTm->Reserved2[ii] = 0;
 
        pScsiTm->TaskMsgContext = 0;
-       dtmprintk((MYIOC_s_INFO_FMT "mptctl_bus_reset: issued.\n", ioctl->ioc->name));
+       dtmprintk((MYIOC_s_INFO_FMT
+               "mptctl_bus_reset: issued.\n", ioctl->ioc->name));
 
-       ioctl->tmPtr = mf;
-       ioctl->TMtimer.expires = jiffies + HZ * 20;     /* 20 seconds */
-       ioctl->status |= MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
-       add_timer(&ioctl->TMtimer);
+       DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
 
-       retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc->id,
-                       sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, NO_SLEEP);
+       ioctl->wait_done=0;
+       if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->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));
+               goto mptctl_bus_reset_done;
+       }
 
-       if (retval != 0) {
-               dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
-                       " (hd %p, ioc %p, mf %p) \n", ioctl->ioc->name, hd, hd->ioc, mf));
+       /* Now wait for the command to complete */
+       ii = wait_event_timeout(mptctl_wait,
+            ioctl->wait_done == 1,
+            HZ*5 /* 5 second timeout */);
 
-               mptctl_free_tm_flags(ioctl->ioc);
-               del_timer(&ioctl->TMtimer);
-               mpt_free_msg_frame(mptctl_id, ioctl->ioc->id, mf);
-               ioctl->tmPtr = NULL;
+       if(ii <=0 && (ioctl->wait_done != 1 ))  {
+               mpt_free_msg_frame(hd->ioc, mf);
+               ioctl->wait_done = 0;
+               retval = -1; /* return failure */
        }
 
+mptctl_bus_reset_done:
+
+       mptctl_free_tm_flags(ioctl->ioc);
        return retval;
 }
 
@@ -483,14 +438,13 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc)
 
        spin_lock_irqsave(&ioc->FreeQlock, flags);
 
-       hd->tmState = TM_STATE_ERROR;
+       hd->tmState = TM_STATE_NONE;
        hd->tmPending = 0;
        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
        return;
 }
 
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /* mptctl_ioc_reset
  *
@@ -503,78 +457,88 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
        MPT_IOCTL *ioctl = ioc->ioctl;
        dctlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to IOCTL driver!\n",
-                       reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
-                       reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
+               reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
+               reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
 
-       if (reset_phase == MPT_IOC_SETUP_RESET){
-               ;
-       } else if (reset_phase == MPT_IOC_PRE_RESET){
-
-               /* Someone has called the reset handler to
-                * do a hard reset. No more replies from the FW.
-                * Delete the timer. TM flags cleaned up by SCSI driver.
-                * Do not need to free msg frame, as re-initialized
-                */
-               if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){
-                       del_timer(&ioctl->timer);
-               }
-               if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){
-                       ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
-                       del_timer(&ioctl->TMtimer);
-                       mpt_free_msg_frame(mptctl_id, ioc->id, ioctl->tmPtr);
-               }
-
-       } else {
-               ioctl->tmPtr = NULL;
-
-               /* Set the status and continue IOCTL
-                * processing. All memory will be free'd
-                * by originating thread after wake_up is
-                * called.
-                */
-               if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){
-                       ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
+       if(ioctl == NULL)
+               return 1;
 
-                       /* Wake up the calling process
-                        */
-                       ioctl->wait_done = 1;
-                       wake_up(&mptctl_wait);
-               }
+       switch(reset_phase) {
+       case MPT_IOC_SETUP_RESET:
+               ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
+               break;
+       case MPT_IOC_POST_RESET:
+               ioctl->status &= ~MPT_IOCTL_STATUS_DID_IOCRESET;
+               break;
+       case MPT_IOC_PRE_RESET:
+       default:
+               break;
        }
 
        return 1;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  struct file_operations functionality.
- *  Members:
- *     llseek, write, read, ioctl, open, release
- */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9)
-static loff_t
-mptctl_llseek(struct file *file, loff_t offset, int origin)
+/* ASYNC Event Notification Support */
+static int
+mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
-       return -ESPIPE;
+       u8 event;
+
+       event = le32_to_cpu(pEvReply->Event) & 0xFF;
+
+       dctlprintk(("%s() called\n", __FUNCTION__));
+       if(async_queue == NULL)
+               return 1;
+
+       /* Raise SIGIO for persistent events.
+        * TODO - this define is not in MPI spec yet,
+        * but they plan to set it to 0x21
+        */
+        if (event == 0x21 ) {
+               ioc->aen_event_read_flag=1;
+               dctlprintk(("Raised SIGIO to application\n"));
+               devtverboseprintk(("Raised SIGIO to application\n"));
+               kill_fasync(&async_queue, SIGIO, POLL_IN);
+               return 1;
+        }
+
+       /* This flag is set after SIGIO was raised, and
+        * remains set until the application has read
+        * the event log via ioctl=MPTEVENTREPORT
+        */
+       if(ioc->aen_event_read_flag)
+               return 1;
+
+       /* Signal only for the events that are
+        * requested for by the application
+        */
+       if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
+               ioc->aen_event_read_flag=1;
+               dctlprintk(("Raised SIGIO to application\n"));
+               devtverboseprintk(("Raised SIGIO to application\n"));
+               kill_fasync(&async_queue, SIGIO, POLL_IN);
+       }
+       return 1;
 }
-#define no_llseek mptctl_llseek
-#endif
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static ssize_t
-mptctl_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+static int
+mptctl_fasync(int fd, struct file *filep, int mode)
 {
-       printk(KERN_ERR MYNAM ": ioctl WRITE not yet supported\n");
-       return 0;
+       MPT_ADAPTER     *ioc;
+
+       list_for_each_entry(ioc, &ioc_list, list)
+               ioc->aen_event_read_flag=0;
+
+       dctlprintk(("%s() called\n", __FUNCTION__));
+       return fasync_helper(fd, filep, mode, &async_queue);
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static ssize_t
-mptctl_read(struct file *file, char *buf, size_t count, loff_t *ptr)
+static int
+mptctl_release(struct inode *inode, struct file *filep)
 {
-       printk(KERN_ERR MYNAM ": ioctl READ not yet supported\n");
-       return 0;
+       dctlprintk(("%s() called\n", __FUNCTION__));
+       return fasync_helper(-1, filep, 0, &async_queue);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -583,10 +547,10 @@ mptctl_read(struct file *file, char *buf, size_t count, loff_t *ptr)
  *  cmd - specify the particular IOCTL command to be issued
  *  arg - data specific to the command. Must not be null.
  */
-static int
-mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long
+__mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       mpt_ioctl_header        *uhdr = (mpt_ioctl_header *) arg;
+       mpt_ioctl_header __user *uhdr = (void __user *) arg;
        mpt_ioctl_header         khdr;
        int iocnum;
        unsigned iocnumX;
@@ -599,7 +563,7 @@ mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
        if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
                printk(KERN_ERR "%s::mptctl_ioctl() @%d - "
                                "Unable to copy mpt_ioctl_header data @ %p\n",
-                               __FILE__, __LINE__, (void*)uhdr);
+                               __FILE__, __LINE__, uhdr);
                return -EFAULT;
        }
        ret = -ENXIO;                           /* (-6) No such device or address */
@@ -663,15 +627,24 @@ mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
        else
                ret = -EINVAL;
 
+       mutex_unlock(&iocp->ioctl->ioctl_mutex);
 
-       up(&mptctl_syscall_sem_ioc[iocp->id]);
+       return ret;
+}
 
+static long
+mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       long ret;
+       lock_kernel();
+       ret = __mptctl_ioctl(file, cmd, arg);
+       unlock_kernel();
        return ret;
 }
 
 static int mptctl_do_reset(unsigned long arg)
 {
-       struct mpt_ioctl_diag_reset *urinfo = (struct mpt_ioctl_diag_reset *) arg;
+       struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
        struct mpt_ioctl_diag_reset krinfo;
        MPT_ADAPTER             *iocp;
 
@@ -680,7 +653,7 @@ static int mptctl_do_reset(unsigned long arg)
        if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
                printk(KERN_ERR "%s@%d::mptctl_do_reset - "
                                "Unable to copy mpt_ioctl_diag_reset struct @ %p\n",
-                               __FILE__, __LINE__, (void*)urinfo);
+                               __FILE__, __LINE__, urinfo);
                return -EFAULT;
        }
 
@@ -699,21 +672,6 @@ static int mptctl_do_reset(unsigned long arg)
        return 0;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int mptctl_open(struct inode *inode, struct file *file)
-{
-       /*
-        * Should support multiple management users
-        */
-       return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int mptctl_release(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  * MPT FW download function.  Cast the arg into the mpt_fw_xfer structure.
@@ -734,14 +692,14 @@ static int mptctl_release(struct inode *inode, struct file *file)
 static int
 mptctl_fw_download(unsigned long arg)
 {
-       struct mpt_fw_xfer      *ufwdl = (struct mpt_fw_xfer *) arg;
+       struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
        struct mpt_fw_xfer       kfwdl;
 
        dctlprintk((KERN_INFO "mptctl_fwdl called. mptctl_id = %xh\n", mptctl_id)); //tc
        if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) {
                printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
                                "Unable to copy mpt_fw_xfer struct @ %p\n",
-                               __FILE__, __LINE__, (void*)ufwdl);
+                               __FILE__, __LINE__, ufwdl);
                return -EFAULT;
        }
 
@@ -763,7 +721,7 @@ mptctl_fw_download(unsigned long arg)
  *             -ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
+mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
 {
        FWDownload_t            *dlmsg;
        MPT_FRAME_HDR           *mf;
@@ -782,26 +740,27 @@ mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
        u32                      nib;
        int                      fw_bytes_copied = 0;
        int                      i;
-       int                      cntdn;
        int                      sge_offset = 0;
        u16                      iocstat;
+       pFWDownloadReply_t       ReplyMsg = NULL;
 
-       dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
+       dctlprintk(("mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
 
-       dctlprintk((KERN_INFO "DbG: kfwdl.bufp  = %p\n", ufwbuf));
-       dctlprintk((KERN_INFO "DbG: kfwdl.fwlen = %d\n", (int)fwlen));
-       dctlprintk((KERN_INFO "DbG: kfwdl.ioc   = %04xh\n", ioc));
+       dctlprintk(("DbG: kfwdl.bufp  = %p\n", ufwbuf));
+       dctlprintk(("DbG: kfwdl.fwlen = %d\n", (int)fwlen));
+       dctlprintk(("DbG: kfwdl.ioc   = %04xh\n", ioc));
 
-       if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) {
-               dctlprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n",
-                               __FILE__, __LINE__, ioc));
+       if (mpt_verify_adapter(ioc, &iocp) < 0) {
+               dctlprintk(("ioctl_fwdl - ioc%d not found!\n",
+                                ioc));
                return -ENODEV; /* (-6) No such device or address */
-       }
+       } else {
 
-       /*  Valid device. Get a message frame and construct the FW download message.
-        */
-       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
-               return -EAGAIN;
+               /*  Valid device. Get a message frame and construct the FW download message.
+               */
+               if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+                       return -EAGAIN;
+       }
        dlmsg = (FWDownload_t*) mf;
        ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
        sgOut = (char *) (ptsge + 1);
@@ -814,7 +773,11 @@ mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
        dlmsg->ChainOffset = 0;
        dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD;
        dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0;
-       dlmsg->MsgFlags = 0;
+       if (iocp->facts.MsgVersion >= MPI_VERSION_01_05)
+               dlmsg->MsgFlags = MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT;
+       else
+               dlmsg->MsgFlags = 0;
+
 
        /* Set up the Transaction SGE.
         */
@@ -866,7 +829,7 @@ mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
                goto fwdl_out;
        }
 
-       dctlprintk((KERN_INFO "DbG: sgl buffer  = %p, sgfrags = %d\n", sgl, numfrags));
+       dctlprintk(("DbG: sgl buffer  = %p, sgfrags = %d\n", sgl, numfrags));
 
        /*
         * Parse SG list, copying sgl itself,
@@ -892,7 +855,7 @@ mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
                        if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
                                printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
                                                "Unable to copy f/w buffer hunk#%d @ %p\n",
-                                               __FILE__, __LINE__, n, (void*)ufwbuf);
+                                               __FILE__, __LINE__, n, ufwbuf);
                                goto fwdl_out;
                        }
                        fw_bytes_copied += bl->len;
@@ -916,30 +879,24 @@ mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen)
         * Finally, perform firmware download.
         */
        ReplyMsg = NULL;
-       mpt_put_msg_frame(mptctl_id, ioc, mf);
-
-       /*
-        *  Wait until the reply has been received
-        */
-       for (cntdn=HZ*60, i=1; ReplyMsg == NULL; cntdn--, i++) {
-               if (!cntdn) {
-                       ret = -ETIME;
-                       goto fwdl_out;
-               }
+       mpt_put_msg_frame(mptctl_id, iocp, mf);
 
-               if (!(i%HZ)) {
-                       dctlprintk((KERN_INFO "DbG::_do_fwdl: "
-                                  "In ReplyMsg loop - iteration %d\n",
-                                  i));
-               }
+       /* Now wait for the command to complete */
+       ret = wait_event_timeout(mptctl_wait,
+            iocp->ioctl->wait_done == 1,
+            HZ*60);
 
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
+       if(ret <=0 && (iocp->ioctl->wait_done != 1 )) {
+       /* Now we need to reset the board */
+               mptctl_timeout_expired(iocp->ioctl);
+               ret = -ENODATA;
+               goto fwdl_out;
        }
 
        if (sgl)
                kfree_sgl(sgl, sgl_dma, buflist, iocp);
 
+       ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame;
        iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
        if (iocstat == MPI_IOCSTATUS_SUCCESS) {
                printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name);
@@ -1198,8 +1155,8 @@ kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTE
 static int
 mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 {
-       struct mpt_ioctl_iocinfo *uarg = (struct mpt_ioctl_iocinfo *) arg;
-       struct mpt_ioctl_iocinfo karg;
+       struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_iocinfo *karg;
        MPT_ADAPTER             *ioc;
        struct pci_dev          *pdev;
        struct Scsi_Host        *sh;
@@ -1208,7 +1165,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
        int                     numDevices = 0;
        unsigned int            max_id;
        int                     ii;
-       int                     port;
+       unsigned int            port;
        int                     cim_rev;
        u8                      revision;
 
@@ -1219,64 +1176,83 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
         */
        if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev0))
                cim_rev = 0;
-       else if (data_size == sizeof(struct mpt_ioctl_iocinfo))
+       else if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev1))
                cim_rev = 1;
+       else if (data_size == sizeof(struct mpt_ioctl_iocinfo))
+               cim_rev = 2;
        else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12))
                cim_rev = 0;    /* obsolete */
        else
                return -EFAULT;
 
-       if (copy_from_user(&karg, uarg, data_size)) {
+       karg = kmalloc(data_size, GFP_KERNEL);
+       if (karg == NULL) {
+               printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
+                               __FILE__, __LINE__);
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(karg, uarg, data_size)) {
                printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
                        "Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
+               kfree(karg);
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+       if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
            (ioc == NULL)) {
                dctlprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
                                __FILE__, __LINE__, iocnum));
+               kfree(karg);
                return -ENODEV;
        }
 
-       /* Verify the data transfer size is correct.
-        * Ignore the port setting.
-        */
-       if (karg.hdr.maxDataSize != data_size) {
+       /* Verify the data transfer size is correct. */
+       if (karg->hdr.maxDataSize != data_size) {
                printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
                        "Structure size mismatch. Command not completed.\n",
                                __FILE__, __LINE__);
+               kfree(karg);
                return -EFAULT;
        }
 
        /* Fill in the data and return the structure to the calling
         * program
         */
-       if ((int)ioc->chip_type <= (int) FC929)
-               karg.adapterType = MPT_IOCTL_INTERFACE_FC;
+       if (ioc->bus_type == SAS)
+               karg->adapterType = MPT_IOCTL_INTERFACE_SAS;
+       else if (ioc->bus_type == FC)
+               karg->adapterType = MPT_IOCTL_INTERFACE_FC;
        else
-               karg.adapterType = MPT_IOCTL_INTERFACE_SCSI;
+               karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
 
-       port = karg.hdr.port;
+       if (karg->hdr.port > 1)
+               return -EINVAL;
+       port = karg->hdr.port;
 
-       karg.port = port;
+       karg->port = port;
        pdev = (struct pci_dev *) ioc->pcidev;
 
-       karg.pciId = pdev->device;
+       karg->pciId = pdev->device;
        pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
-       karg.hwRev = revision;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-       karg.subSystemDevice = pdev->subsystem_device;
-       karg.subSystemVendor = pdev->subsystem_vendor;
-#endif
+       karg->hwRev = revision;
+       karg->subSystemDevice = pdev->subsystem_device;
+       karg->subSystemVendor = pdev->subsystem_vendor;
 
        if (cim_rev == 1) {
                /* Get the PCI bus, device, and function numbers for the IOC
                 */
-               karg.pciInfo.u.bits.busNumber = pdev->bus->number;
-               karg.pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
-               karg.pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
+               karg->pciInfo.u.bits.busNumber = pdev->bus->number;
+               karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
+               karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
+       } else if (cim_rev == 2) {
+               /* Get the PCI bus, device, function and segment ID numbers
+                  for the IOC */
+               karg->pciInfo.u.bits.busNumber = pdev->bus->number;
+               karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );
+               karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
+               karg->pciInfo.segmentID = pci_domain_nr(pdev->bus);
        }
 
        /* Get number of devices
@@ -1297,31 +1273,33 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
                        }
                }
        }
-       karg.numDevices = numDevices;
+       karg->numDevices = numDevices;
 
        /* Set the BIOS and FW Version
         */
-       karg.FWVersion = ioc->facts.FWVersion.Word;
-       karg.BIOSVersion = ioc->biosVersion;
+       karg->FWVersion = ioc->facts.FWVersion.Word;
+       karg->BIOSVersion = ioc->biosVersion;
 
        /* Set the Version Strings.
         */
-       strncpy (karg.driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH);
-       karg.driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0';
+       strncpy (karg->driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH);
+       karg->driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0';
 
-       karg.busChangeEvent = 0;
-       karg.hostId = ioc->pfacts[port].PortSCSIID;
-       karg.rsvd[0] = karg.rsvd[1] = 0;
+       karg->busChangeEvent = 0;
+       karg->hostId = ioc->pfacts[port].PortSCSIID;
+       karg->rsvd[0] = karg->rsvd[1] = 0;
 
        /* Copy the data from kernel memory to user memory
         */
-       if (copy_to_user((char *)arg, &karg, data_size)) {
+       if (copy_to_user((char __user *)arg, karg, data_size)) {
                printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
                        "Unable to write out mpt_ioctl_iocinfo struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
+               kfree(karg);
                return -EFAULT;
        }
 
+       kfree(karg);
        return 0;
 }
 
@@ -1338,15 +1316,16 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 static int
 mptctl_gettargetinfo (unsigned long arg)
 {
-       struct mpt_ioctl_targetinfo *uarg = (struct mpt_ioctl_targetinfo *) arg;
+       struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
        struct mpt_ioctl_targetinfo karg;
        MPT_ADAPTER             *ioc;
        struct Scsi_Host        *sh;
        MPT_SCSI_HOST           *hd;
-       VirtDevice              *vdev;
+       VirtTarget              *vdev;
        char                    *pmem;
        int                     *pdata;
        IOCPage2_t              *pIoc2;
+       IOCPage3_t              *pIoc3;
        int                     iocnum;
        int                     numDevices = 0;
        unsigned int            max_id;
@@ -1360,7 +1339,7 @@ mptctl_gettargetinfo (unsigned long arg)
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
                printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
                        "Unable to read in mpt_ioctl_targetinfo struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -1422,54 +1401,58 @@ mptctl_gettargetinfo (unsigned long arg)
                 */
                if (hd && hd->Targets) {
                        mpt_findImVolumes(ioc);
-                       pIoc2 = ioc->spi_data.pIocPg2;
-                       for ( id = 0; id <= max_id; id++ ) {
-                               if ( pIoc2 && pIoc2->NumActiveVolumes &&
-                                       ( id == pIoc2->RaidVolume[0].VolumeID ) ) {
-                                       if (maxWordsLeft <= 0) {
-                                               printk(KERN_ERR "mptctl_gettargetinfo - "
+                       pIoc2 = ioc->raid_data.pIocPg2;
+                       for ( id = 0; id <= max_id; ) {
+                               if ( pIoc2 && pIoc2->NumActiveVolumes ) {
+                                       if ( id == pIoc2->RaidVolume[0].VolumeID ) {
+                                               if (maxWordsLeft <= 0) {
+                                                       printk(KERN_ERR "mptctl_gettargetinfo - "
                        "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
-                                               goto data_space_full;
-                                       }
-                                       if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
-                                               devType = 0x80;
-                                       else
-                                               devType = 0xC0;
-                                       bus_id = pIoc2->RaidVolume[0].VolumeBus;
-                                       numDevices++;
-                                       *pdata = ( (devType << 24) | (bus_id << 8) | id );
-                                       dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
+                                                       goto data_space_full;
+                                               }
+                                               if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
+                                                       devType = 0x80;
+                                               else
+                                                       devType = 0xC0;
+                                               bus_id = pIoc2->RaidVolume[0].VolumeBus;
+                                               numDevices++;
+                                               *pdata = ( (devType << 24) | (bus_id << 8) | id );
+                                               dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
                "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
-                                       pdata++;
-                                       --maxWordsLeft;
-                               } else {
-                                       vdev = hd->Targets[id];
-                                       if (vdev) {
-                                               for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
-                                                       lun_index = (jj >> 5);
-                                                       indexed_lun = (jj % 32);
-                                                       lun = (1 << indexed_lun);
-                                                       if (vdev->luns[lun_index] & lun) {
-                                                               if (maxWordsLeft <= 0) {
-                                                                       printk(KERN_ERR
-                                                                       "mptctl_gettargetinfo - "
-                                                                       "buffer is full but more targets are available on ioc %d numDevices=%d\n",
-                                                                       iocnum, numDevices);
-                                                                       goto data_space_full;
-                                                               }
-                                                               bus_id = vdev->bus_id;
-                                                               numDevices++;
-                                                               *pdata = ( (jj << 16) | (bus_id << 8) | id );
-                                                               dctlprintk((KERN_ERR
-                                                                "mptctl_gettargetinfo - "
-                                                                "target ioc=%d target=%x numDevices=%d pdata=%p\n",
-                                                                iocnum, *pdata, numDevices, pdata));
-                                                               pdata++;
-                                                               --maxWordsLeft;
+                                               pdata++;
+                                               --maxWordsLeft;
+                                               goto next_id;
+                                       } else {
+                                               pIoc3 = ioc->raid_data.pIocPg3;
+                                               for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
+                                                       if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
+                                                               goto next_id;
+                                               }
+                                       }
+                               }
+                               if ( (vdev = hd->Targets[id]) ) {
+                                       for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
+                                               lun_index = (jj >> 5);
+                                               indexed_lun = (jj % 32);
+                                               lun = (1 << indexed_lun);
+                                               if (vdev->luns[lun_index] & lun) {
+                                                       if (maxWordsLeft <= 0) {
+                                                               printk(KERN_ERR "mptctl_gettargetinfo - "
+                       "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
+                                                               goto data_space_full;
                                                        }
+                                                       bus_id = vdev->bus_id;
+                                                       numDevices++;
+                                                       *pdata = ( (jj << 16) | (bus_id << 8) | id );
+                                                       dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
+               "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
+                                                       pdata++;
+                                                       --maxWordsLeft;
                                                }
                                        }
                                }
+next_id:
+                               id++;
                        }
                }
        }
@@ -1478,21 +1461,21 @@ data_space_full:
 
        /* Copy part of the data from kernel memory to user memory
         */
-       if (copy_to_user((char *)arg, &karg,
+       if (copy_to_user((char __user *)arg, &karg,
                                sizeof(struct mpt_ioctl_targetinfo))) {
                printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
                        "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                kfree(pmem);
                return -EFAULT;
        }
 
        /* Copy the remaining data from kernel memory to user memory
         */
-       if (copy_to_user((char *) uarg->targetInfo, pmem, numBytes)) {
+       if (copy_to_user(uarg->targetInfo, pmem, numBytes)) {
                printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
                        "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-                               __FILE__, __LINE__, (void*)pdata);
+                               __FILE__, __LINE__, pdata);
                kfree(pmem);
                return -EFAULT;
        }
@@ -1513,7 +1496,7 @@ data_space_full:
 static int
 mptctl_readtest (unsigned long arg)
 {
-       struct mpt_ioctl_test   *uarg = (struct mpt_ioctl_test *) arg;
+       struct mpt_ioctl_test __user *uarg = (void __user *) arg;
        struct mpt_ioctl_test    karg;
        MPT_ADAPTER *ioc;
        int iocnum;
@@ -1522,7 +1505,7 @@ mptctl_readtest (unsigned long arg)
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
                printk(KERN_ERR "%s@%d::mptctl_readtest - "
                        "Unable to read in mpt_ioctl_test struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -1540,7 +1523,7 @@ mptctl_readtest (unsigned long arg)
 #ifdef MFCNT
        karg.chip_type = ioc->mfcnt;
 #else
-       karg.chip_type = ioc->chip_type;
+       karg.chip_type = ioc->pcidev->device;
 #endif
        strncpy (karg.name, ioc->name, MPT_MAX_NAME);
        karg.name[MPT_MAX_NAME-1]='\0';
@@ -1549,10 +1532,10 @@ mptctl_readtest (unsigned long arg)
 
        /* Copy the data from kernel memory to user memory
         */
-       if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
+       if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
                printk(KERN_ERR "%s@%d::mptctl_readtest - "
                        "Unable to write out mpt_ioctl_test struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -1573,7 +1556,7 @@ mptctl_readtest (unsigned long arg)
 static int
 mptctl_eventquery (unsigned long arg)
 {
-       struct mpt_ioctl_eventquery     *uarg = (struct mpt_ioctl_eventquery *) arg;
+       struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
        struct mpt_ioctl_eventquery      karg;
        MPT_ADAPTER *ioc;
        int iocnum;
@@ -1582,7 +1565,7 @@ mptctl_eventquery (unsigned long arg)
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
                printk(KERN_ERR "%s@%d::mptctl_eventquery - "
                        "Unable to read in mpt_ioctl_eventquery struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -1593,15 +1576,15 @@ mptctl_eventquery (unsigned long arg)
                return -ENODEV;
        }
 
-       karg.eventEntries = ioc->eventLogSize;
+       karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
        karg.eventTypes = ioc->eventTypes;
 
        /* Copy the data from kernel memory to user memory
         */
-       if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
+       if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
                printk(KERN_ERR "%s@%d::mptctl_eventquery - "
                        "Unable to write out mpt_ioctl_eventquery struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
        return 0;
@@ -1611,7 +1594,7 @@ mptctl_eventquery (unsigned long arg)
 static int
 mptctl_eventenable (unsigned long arg)
 {
-       struct mpt_ioctl_eventenable    *uarg = (struct mpt_ioctl_eventenable *) arg;
+       struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
        struct mpt_ioctl_eventenable     karg;
        MPT_ADAPTER *ioc;
        int iocnum;
@@ -1620,7 +1603,7 @@ mptctl_eventenable (unsigned long arg)
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
                printk(KERN_ERR "%s@%d::mptctl_eventenable - "
                        "Unable to read in mpt_ioctl_eventenable struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -1643,7 +1626,6 @@ mptctl_eventenable (unsigned long arg)
                memset(ioc->events, 0, sz);
                ioc->alloc_total += sz;
 
-               ioc->eventLogSize = MPTCTL_EVENT_LOG_SIZE;
                ioc->eventContext = 0;
         }
 
@@ -1658,7 +1640,7 @@ mptctl_eventenable (unsigned long arg)
 static int
 mptctl_eventreport (unsigned long arg)
 {
-       struct mpt_ioctl_eventreport    *uarg = (struct mpt_ioctl_eventreport *) arg;
+       struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
        struct mpt_ioctl_eventreport     karg;
        MPT_ADAPTER              *ioc;
        int                      iocnum;
@@ -1668,7 +1650,7 @@ mptctl_eventreport (unsigned long arg)
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
                printk(KERN_ERR "%s@%d::mptctl_eventreport - "
                        "Unable to read in mpt_ioctl_eventreport struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -1683,7 +1665,7 @@ mptctl_eventreport (unsigned long arg)
        maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS);
 
 
-       max = ioc->eventLogSize < maxEvents ? ioc->eventLogSize : maxEvents;
+       max = MPTCTL_EVENT_LOG_SIZE < maxEvents ? MPTCTL_EVENT_LOG_SIZE : maxEvents;
 
        /* If fewer than 1 event is requested, there must have
         * been some type of error.
@@ -1691,13 +1673,16 @@ mptctl_eventreport (unsigned long arg)
        if ((max < 1) || !ioc->events)
                return -ENODATA;
 
+       /* reset this flag so SIGIO can restart */
+       ioc->aen_event_read_flag=0;
+
        /* Copy the data from kernel memory to user memory
         */
        numBytes = max * sizeof(MPT_IOCTL_EVENTS);
-       if (copy_to_user((char *) uarg->eventData, ioc->events, numBytes)) {
+       if (copy_to_user(uarg->eventData, ioc->events, numBytes)) {
                printk(KERN_ERR "%s@%d::mptctl_eventreport - "
                        "Unable to write out mpt_ioctl_eventreport struct @ %p\n",
-                               __FILE__, __LINE__, (void*)ioc->events);
+                               __FILE__, __LINE__, ioc->events);
                return -EFAULT;
        }
 
@@ -1708,21 +1693,17 @@ mptctl_eventreport (unsigned long arg)
 static int
 mptctl_replace_fw (unsigned long arg)
 {
-       struct mpt_ioctl_replace_fw     *uarg = (struct mpt_ioctl_replace_fw *) arg;
+       struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
        struct mpt_ioctl_replace_fw      karg;
        MPT_ADAPTER              *ioc;
-       fw_image_t               **fwmem = NULL;
        int                      iocnum;
        int                      newFwSize;
-       int                      num_frags, alloc_sz;
-       int                      ii;
-       u32                      offset;
 
        dctlprintk(("mptctl_replace_fw called.\n"));
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
                printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
                        "Unable to read in mpt_ioctl_replace_fw struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -1733,52 +1714,39 @@ mptctl_replace_fw (unsigned long arg)
                return -ENODEV;
        }
 
-       /* If not caching FW, return 0
+       /* If caching FW, Free the old FW image
         */
-       if ((ioc->cached_fw == NULL) && (ioc->alt_ioc) && (ioc->alt_ioc->cached_fw == NULL))
+       if (ioc->cached_fw == NULL)
                return 0;
 
+       mpt_free_fw_memory(ioc);
+
        /* Allocate memory for the new FW image
         */
        newFwSize = karg.newImageSize;
-       fwmem = mpt_alloc_fw_memory(ioc, newFwSize, &num_frags, &alloc_sz);
-       if (fwmem == NULL)
-               return -ENOMEM;
-
-       offset = 0;
-       for (ii = 0; ii < num_frags; ii++) {
-               /* Copy the data from user memory to kernel space
-                */
-               if (copy_from_user(fwmem[ii]->fw, uarg->newImage + offset, fwmem[ii]->size)) {
-                       printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
-                               "Unable to read in mpt_ioctl_replace_fw image @ %p\n",
-                                       __FILE__, __LINE__, (void*)uarg);
 
-                       mpt_free_fw_memory(ioc, fwmem);
-                       return -EFAULT;
-               }
-               offset += fwmem[ii]->size;
-       }
+       if (newFwSize & 0x01)
+               newFwSize += 1;
+       if (newFwSize & 0x02)
+               newFwSize += 2;
 
+       mpt_alloc_fw_memory(ioc, newFwSize);
+       if (ioc->cached_fw == NULL)
+               return -ENOMEM;
 
-       /* Free the old FW image
+       /* Copy the data from user memory to kernel space
         */
-       if (ioc->cached_fw) {
-               mpt_free_fw_memory(ioc, 0);
-               ioc->cached_fw = fwmem;
-               ioc->alloc_total += alloc_sz;
-       } else if ((ioc->alt_ioc) && (ioc->alt_ioc->cached_fw)) {
-               mpt_free_fw_memory(ioc->alt_ioc, 0);
-               ioc->alt_ioc->cached_fw = fwmem;
-               ioc->alt_ioc->alloc_total += alloc_sz;
+       if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
+               printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
+                               "Unable to read in mpt_ioctl_replace_fw image "
+                               "@ %p\n", __FILE__, __LINE__, uarg);
+               mpt_free_fw_memory(ioc);
+               return -EFAULT;
        }
 
        /* Update IOCFactsReply
         */
        ioc->facts.FWImageSize = newFwSize;
-       if (ioc->alt_ioc)
-               ioc->alt_ioc->facts.FWImageSize = newFwSize;
-
        return 0;
 }
 
@@ -1797,7 +1765,7 @@ mptctl_replace_fw (unsigned long arg)
 static int
 mptctl_mpt_command (unsigned long arg)
 {
-       struct mpt_ioctl_command *uarg = (struct mpt_ioctl_command *) arg;
+       struct mpt_ioctl_command __user *uarg = (void __user *) arg;
        struct mpt_ioctl_command  karg;
        MPT_ADAPTER     *ioc;
        int             iocnum;
@@ -1808,7 +1776,7 @@ mptctl_mpt_command (unsigned long arg)
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) {
                printk(KERN_ERR "%s@%d::mptctl_mpt_command - "
                        "Unable to read in mpt_ioctl_command struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -1819,7 +1787,7 @@ mptctl_mpt_command (unsigned long arg)
                return -ENODEV;
        }
 
-       rc = mptctl_do_mpt_command (karg, (char *) &uarg->MF, 0);
+       rc = mptctl_do_mpt_command (karg, &uarg->MF);
 
        return rc;
 }
@@ -1837,7 +1805,7 @@ mptctl_mpt_command (unsigned long arg)
  *             -EPERM if SCSI I/O and target is untagged
  */
 static int
-mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
+mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 {
        MPT_ADAPTER     *ioc;
        MPT_FRAME_HDR   *mf = NULL;
@@ -1847,13 +1815,12 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
        struct buflist  bufOut; /* data Out buffer */
        dma_addr_t      dma_addr_in;
        dma_addr_t      dma_addr_out;
-       int             dir;    /* PCI data direction */
        int             sgSize = 0;     /* Num SG elements */
        int             iocnum, flagsLength;
        int             sz, rc = 0;
        int             msgContext;
-       int             tm_flags_set = 0;
        u16             req_idx;
+       ulong           timeout;
 
        dctlprintk(("mptctl_do_mpt_command called.\n"));
        bufIn.kptr = bufOut.kptr = NULL;
@@ -1892,7 +1859,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
 
        /* Get a free request frame and save the message context.
         */
-        if ((mf = mpt_get_msg_frame(mptctl_id, ioc->id)) == NULL)
+        if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
                 return -EAGAIN;
 
        hdr = (MPIHeader_t *) mf;
@@ -1901,23 +1868,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
 
        /* Copy the request frame
         * Reset the saved message context.
+        * Request frame in user space
         */
-        if (local) {
-               /* Request frame in kernel space
-                */
-               memcpy((char *)mf, (char *) mfPtr, karg.dataSgeOffset * 4);
-        } else {
-               /* Request frame in user space
-                */
-               if (copy_from_user((char *)mf, (char *) mfPtr,
-                                       karg.dataSgeOffset * 4)){
-                       printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
-                               "Unable to read MF from mpt_ioctl_command struct @ %p\n",
-                               __FILE__, __LINE__, (void*)mfPtr);
-                       rc = -EFAULT;
-                       goto done_free_mem;
-               }
-        }
+       if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) {
+               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       "Unable to read MF from mpt_ioctl_command struct @ %p\n",
+                       __FILE__, __LINE__, mfPtr);
+               rc = -EFAULT;
+               goto done_free_mem;
+       }
        hdr->MsgContext = cpu_to_le32(msgContext);
 
 
@@ -1936,12 +1895,14 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
        case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
        case MPI_FUNCTION_FW_DOWNLOAD:
        case MPI_FUNCTION_FC_PRIMITIVE_SEND:
+       case MPI_FUNCTION_TOOLBOX:
+       case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
                break;
 
        case MPI_FUNCTION_SCSI_IO_REQUEST:
                if (ioc->sh) {
                        SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
-                       VirtDevice      *pTarget = NULL;
+                       VirtTarget      *pTarget = NULL;
                        MPT_SCSI_HOST   *hd = NULL;
                        int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
                        int scsidir = 0;
@@ -1956,7 +1917,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
                                goto done_free_mem;
                        }
 
-                       pScsiReq->MsgFlags = mpt_msg_flags();
+                       pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
+                       pScsiReq->MsgFlags |= mpt_msg_flags();
+
 
                        /* verify that app has not requested
                         *      more sense data than driver
@@ -2007,6 +1970,25 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
                }
                break;
 
+       case MPI_FUNCTION_SMP_PASSTHROUGH:
+               /* Check mf->PassthruFlags to determine if
+                * transfer is ImmediateMode or not.
+                * Immediate mode returns data in the ReplyFrame.
+                * Else, we are sending request and response data
+                * in two SGLs at the end of the mf.
+                */
+               break;
+
+       case MPI_FUNCTION_SATA_PASSTHROUGH:
+               if (!ioc->sh) {
+                       printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               "SCSI driver is not loaded. \n",
+                                       __FILE__, __LINE__);
+                       rc = -EFAULT;
+                       goto done_free_mem;
+               }
+               break;
+
        case MPI_FUNCTION_RAID_ACTION:
                /* Just add a SGE
                 */
@@ -2019,7 +2001,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
                        int scsidir = MPI_SCSIIO_CONTROL_READ;
                        int dataSize;
 
-                       pScsiReq->MsgFlags = mpt_msg_flags();
+                       pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
+                       pScsiReq->MsgFlags |= mpt_msg_flags();
+
 
                        /* verify that app has not requested
                         *      more sense data than driver
@@ -2077,7 +2061,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
                                rc = -EPERM;
                                goto done_free_mem;
                        }
-                       tm_flags_set = 1;
                }
                break;
 
@@ -2165,9 +2148,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
 
                /* Set up the dataOut memory allocation */
                if (karg.dataOutSize > 0) {
-                       dir = PCI_DMA_TODEVICE;
                        if (karg.dataInSize > 0) {
                                flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+                                               MPI_SGE_FLAGS_END_OF_BUFFER |
                                                MPI_SGE_FLAGS_DIRECTION |
                                                mpt_addr_size() )
                                                << MPI_SGE_FLAGS_SHIFT;
@@ -2198,7 +2181,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
                                                "%s@%d::mptctl_do_mpt_command - Unable "
                                                "to read user data "
                                                "struct @ %p\n",
-                                               __FILE__, __LINE__,(void*)karg.dataOutBufPtr);
+                                               __FILE__, __LINE__,karg.dataOutBufPtr);
                                        rc =  -EFAULT;
                                        goto done_free_mem;
                                }
@@ -2206,7 +2189,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
                }
 
                if (karg.dataInSize > 0) {
-                       dir = PCI_DMA_FROMDEVICE;
                        flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
                        flagsLength |= karg.dataInSize;
 
@@ -2230,135 +2212,108 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local)
                mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
        }
 
-       /* The request is complete. Set the timer parameters
-        * and issue the request.
-        */
-       if (karg.timeout > 0) {
-               ioc->ioctl->timer.expires = jiffies + HZ*karg.timeout;
-       } else {
-               ioc->ioctl->timer.expires = jiffies + HZ*MPT_IOCTL_DEFAULT_TIMEOUT;
-       }
-
        ioc->ioctl->wait_done = 0;
-       ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE;
-       add_timer(&ioc->ioctl->timer);
-
        if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
-               rc = mpt_send_handshake_request(mptctl_id, ioc->id,
-                               sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
-               if (rc == 0) {
-                       wait_event(mptctl_wait, ioc->ioctl->wait_done);
-               } else {
+
+               DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
+
+               if (mpt_send_handshake_request(mptctl_id, ioc,
+                       sizeof(SCSITaskMgmt_t), (u32*)mf,
+                       CAN_SLEEP) != 0) {
+                       dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
+                               " (ioc %p, mf %p) \n", ioc->name,
+                               ioc, mf));
                        mptctl_free_tm_flags(ioc);
-                       tm_flags_set= 0;
-                       del_timer(&ioc->ioctl->timer);
-                       ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
-                       ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED;
-                       mpt_free_msg_frame(mptctl_id, ioc->id, mf);
+                       rc = -ENODATA;
+                       goto done_free_mem;
                }
-       } else {
-               mpt_put_msg_frame(mptctl_id, ioc->id, mf);
-               wait_event(mptctl_wait, ioc->ioctl->wait_done);
-       }
 
-       mf = NULL;
+       } else
+               mpt_put_msg_frame(mptctl_id, ioc, mf);
 
-       /* MF Cleanup:
-        * If command failed and failure triggered a diagnostic reset
-        * OR a diagnostic reset happens during command processing,
-        * no data, messaging queues are reset (mf cannot be accessed),
-        * and status is DID_IOCRESET
-        *
-        * If a user-requested bus reset fails to be handshaked, then
-        * mf is returned to free queue and status is TM_FAILED.
-        *
-        * Otherise, the command completed and the mf was freed
-        # by ISR (mf cannot be touched).
-        */
-       if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
-               /* The timer callback deleted the
-                * timer and reset the adapter queues.
-                */
-               printk(KERN_WARNING "%s@%d::mptctl_do_mpt_command - "
-                       "Timeout Occurred on IOCTL! Reset IOC.\n", __FILE__, __LINE__);
-               tm_flags_set= 0;
-               rc = -ETIME;
-       } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TM_FAILED) {
-               /* User TM request failed! mf has not been freed.
-                */
+       /* Now wait for the command to complete */
+       timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
+       timeout = wait_event_timeout(mptctl_wait,
+            ioc->ioctl->wait_done == 1,
+            HZ*timeout);
+
+       if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
+       /* Now we need to reset the board */
+
+               if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT)
+                       mptctl_free_tm_flags(ioc);
+
+               mptctl_timeout_expired(ioc->ioctl);
                rc = -ENODATA;
-       } else {
-               /* If a valid reply frame, copy to the user.
-                * Offset 2: reply length in U32's
-                */
-               if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
-                       if (karg.maxReplyBytes < ioc->reply_sz) {
-                                sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);
-                       } else {
-                                sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);
-                       }
+               goto done_free_mem;
+       }
 
-                       if (sz > 0) {
-                               if (copy_to_user((char *)karg.replyFrameBufPtr,
-                                        &ioc->ioctl->ReplyFrame, sz)){
+       mf = NULL;
 
-                                        printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
-                                        "Unable to write out reply frame %p\n",
-                                        __FILE__, __LINE__, (void*)karg.replyFrameBufPtr);
-                                        rc =  -ENODATA;
-                                        goto done_free_mem;
-                               }
-                       }
+       /* If a valid reply frame, copy to the user.
+        * Offset 2: reply length in U32's
+        */
+       if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+               if (karg.maxReplyBytes < ioc->reply_sz) {
+                        sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);
+               } else {
+                        sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);
                }
 
-               /* If valid sense data, copy to user.
-                */
-               if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
-                       sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
-                       if (sz > 0) {
-                               if (copy_to_user((char *)karg.senseDataPtr, ioc->ioctl->sense, sz)) {
-                                       printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
-                                       "Unable to write sense data to user %p\n",
-                                       __FILE__, __LINE__,
-                                       (void*)karg.senseDataPtr);
-                                       rc =  -ENODATA;
-                                       goto done_free_mem;
-                               }
+               if (sz > 0) {
+                       if (copy_to_user(karg.replyFrameBufPtr,
+                                &ioc->ioctl->ReplyFrame, sz)){
+                                printk(KERN_ERR
+                                    "%s@%d::mptctl_do_mpt_command - "
+                                "Unable to write out reply frame %p\n",
+                                __FILE__, __LINE__, karg.replyFrameBufPtr);
+                                rc =  -ENODATA;
+                                goto done_free_mem;
                        }
                }
+       }
 
-               /* If the overall status is _GOOD and data in, copy data
-                * to user.
-                */
-               if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
-                                       (karg.dataInSize > 0) && (bufIn.kptr)) {
-
-                       if (copy_to_user((char *)karg.dataInBufPtr,
-                                        bufIn.kptr, karg.dataInSize)) {
+       /* If valid sense data, copy to user.
+        */
+       if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
+               sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
+               if (sz > 0) {
+                       if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
                                printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
-                                       "Unable to write data to user %p\n",
-                                       __FILE__, __LINE__,
-                                       (void*)karg.dataInBufPtr);
+                               "Unable to write sense data to user %p\n",
+                               __FILE__, __LINE__,
+                               karg.senseDataPtr);
                                rc =  -ENODATA;
+                               goto done_free_mem;
                        }
                }
        }
 
-done_free_mem:
-       /* Clear all status bits except TMTIMER_ACTIVE, this bit is cleared
-        * upon completion of the TM command.
-        * ioc->ioctl->status = 0;
+       /* If the overall status is _GOOD and data in, copy data
+        * to user.
         */
-       ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_TIMER_ACTIVE | MPT_IOCTL_STATUS_TM_FAILED |
-                       MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
-                       MPT_IOCTL_STATUS_RF_VALID | MPT_IOCTL_STATUS_DID_IOCRESET);
+       if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
+                               (karg.dataInSize > 0) && (bufIn.kptr)) {
 
-       if (tm_flags_set)
-               mptctl_free_tm_flags(ioc);
+               if (copy_to_user(karg.dataInBufPtr,
+                                bufIn.kptr, karg.dataInSize)) {
+                       printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               "Unable to write data to user %p\n",
+                               __FILE__, __LINE__,
+                               karg.dataInBufPtr);
+                       rc =  -ENODATA;
+               }
+       }
+
+done_free_mem:
+
+       ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD |
+               MPT_IOCTL_STATUS_SENSE_VALID |
+               MPT_IOCTL_STATUS_RF_VALID );
 
        /* Free the allocated memory.
         */
-        if (bufOut.kptr != NULL) {
+       if (bufOut.kptr != NULL) {
                pci_free_consistent(ioc->pcidev,
                        bufOut.len, (void *) bufOut.kptr, dma_addr_out);
        }
@@ -2372,13 +2327,13 @@ done_free_mem:
         * otherwise, failure occured after mf acquired.
         */
        if (mf)
-               mpt_free_msg_frame(mptctl_id, ioc->id, mf);
+               mpt_free_msg_frame(ioc, mf);
 
        return rc;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Prototype Routine for the HP HOST INFO command.
+/* Prototype Routine for the HOST INFO command.
  *
  * Outputs:    None.
  * Return:     0 if successful
@@ -2391,16 +2346,19 @@ done_free_mem:
 static int
 mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 {
-       hp_host_info_t  *uarg = (hp_host_info_t *) arg;
+       hp_host_info_t  __user *uarg = (void __user *) arg;
        MPT_ADAPTER             *ioc;
        struct pci_dev          *pdev;
-       char                    *pbuf;
+       char                    *pbuf=NULL;
        dma_addr_t              buf_dma;
        hp_host_info_t          karg;
        CONFIGPARMS             cfg;
        ConfigPageHeader_t      hdr;
        int                     iocnum;
        int                     rc, cim_rev;
+       ToolboxIstwiReadWriteRequest_t  *IstwiRWRequest;
+       MPT_FRAME_HDR           *mf = NULL;
+       MPIHeader_t             *mpi_hdr;
 
        dctlprintk((": mptctl_hp_hostinfo called.\n"));
        /* Reset long to int. Should affect IA64 and SPARC only
@@ -2415,7 +2373,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
        if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
                printk(KERN_ERR "%s@%d::mptctl_hp_host_info - "
                        "Unable to read in hp_host_info struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -2433,10 +2391,8 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 
        karg.vendor = pdev->vendor;
        karg.device = pdev->device;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
        karg.subsystem_id = pdev->subsystem_device;
        karg.subsystem_vendor = pdev->subsystem_vendor;
-#endif
        karg.devfn = pdev->devfn;
        karg.bus = pdev->bus->number;
 
@@ -2473,7 +2429,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
        hdr.PageLength = 0;
        hdr.PageNumber = 0;
        hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
-       cfg.hdr = &hdr;
+       cfg.cfghdr.hdr = &hdr;
        cfg.physAddr = -1;
        cfg.pageAddr = 0;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -2482,7 +2438,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 
        strncpy(karg.serial_number, " ", 24);
        if (mpt_config(ioc, &cfg) == 0) {
-               if (cfg.hdr->PageLength > 0) {
+               if (cfg.cfghdr.hdr->PageLength > 0) {
                        /* Issue the second config page request */
                        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 
@@ -2518,9 +2474,9 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
                break;
        }
 
-       karg.base_io_addr = pdev->PCI_BASEADDR_START(0);
+       karg.base_io_addr = pci_resource_start(pdev, 0);
 
-       if ((int)ioc->chip_type <= (int) FC929)
+       if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
                karg.bus_phys_width = HP_BUS_WIDTH_UNK;
        else
                karg.bus_phys_width = HP_BUS_WIDTH_16;
@@ -2538,27 +2494,73 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
                }
        }
 
-       cfg.pageAddr = 0;
-       cfg.action = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
-       cfg.dir = MPI_TB_ISTWI_FLAGS_READ;
-       cfg.timeout = 10;
+       /* 
+        * Gather ISTWI(Industry Standard Two Wire Interface) Data
+        */
+       if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+               dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+                   ioc->name,__FUNCTION__));
+               goto out;
+       }
+
+       IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf;
+       mpi_hdr = (MPIHeader_t *) mf;
+       memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t));
+       IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX;
+       IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
+       IstwiRWRequest->MsgContext = mpi_hdr->MsgContext;
+       IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ;
+       IstwiRWRequest->NumAddressBytes = 0x01;
+       IstwiRWRequest->DataLength = cpu_to_le16(0x04);
+       if (pdev->devfn & 1)
+               IstwiRWRequest->DeviceAddr = 0xB2;
+       else
+               IstwiRWRequest->DeviceAddr = 0xB0;
+
        pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
-       if (pbuf) {
-               cfg.physAddr = buf_dma;
-               if ((mpt_toolbox(ioc, &cfg)) == 0) {
-                       karg.rsvd = *(u32 *)pbuf;
-               }
+       if (!pbuf)
+               goto out;
+       mpt_add_sge((char *)&IstwiRWRequest->SGL,
+           (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
+
+       ioc->ioctl->wait_done = 0;
+       mpt_put_msg_frame(mptctl_id, ioc, mf);
+
+       rc = wait_event_timeout(mptctl_wait,
+            ioc->ioctl->wait_done == 1,
+            HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
+
+       if(rc <=0 && (ioc->ioctl->wait_done != 1 )) {
+               /* 
+                * Now we need to reset the board
+                */
+               mpt_free_msg_frame(ioc, mf);
+               mptctl_timeout_expired(ioc->ioctl);
+               goto out;
+       }
+
+       /* 
+        *ISTWI Data Definition
+        * pbuf[0] = FW_VERSION = 0x4
+        * pbuf[1] = Bay Count = 6 or 4 or 2, depending on
+        *  the config, you should be seeing one out of these three values
+        * pbuf[2] = Drive Installed Map = bit pattern depend on which
+        *   bays have drives in them
+        * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3)
+        */
+       if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID)
+               karg.rsvd = *(u32 *)pbuf;
+
+ out:
+       if (pbuf)
                pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
-               pbuf = NULL;
-       }
 
        /* Copy the data from kernel memory to user memory
         */
-       if (copy_to_user((char *)arg, &karg,
-                               sizeof(hp_host_info_t))) {
+       if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
                printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - "
                        "Unable to write out hp_host_info @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -2567,7 +2569,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Prototype Routine for the HP TARGET INFO command.
+/* Prototype Routine for the TARGET INFO command.
  *
  * Outputs:    None.
  * Return:     0 if successful
@@ -2580,7 +2582,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 static int
 mptctl_hp_targetinfo(unsigned long arg)
 {
-       hp_target_info_t        *uarg = (hp_target_info_t *) arg;
+       hp_target_info_t __user *uarg = (void __user *) arg;
        SCSIDevicePage0_t       *pg0_alloc;
        SCSIDevicePage3_t       *pg3_alloc;
        MPT_ADAPTER             *ioc;
@@ -2597,10 +2599,10 @@ mptctl_hp_targetinfo(unsigned long arg)
        if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) {
                printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - "
                        "Unable to read in hp_host_targetinfo struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
-       
+
        if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
                (ioc == NULL)) {
                dctlprintk((KERN_ERR "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
@@ -2610,7 +2612,7 @@ mptctl_hp_targetinfo(unsigned long arg)
 
        /*  There is nothing to do for FCP parts.
         */
-       if ((int) ioc->chip_type <= (int) FC929)
+       if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
                return 0;
 
        if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL))
@@ -2618,7 +2620,7 @@ mptctl_hp_targetinfo(unsigned long arg)
 
        if (ioc->sh->host_no != karg.hdr.host)
                return -ENODEV;
-               
+
        /* Get the data transfer speeds
         */
        data_sz = ioc->spi_data.sdp0length * 4;
@@ -2629,7 +2631,7 @@ mptctl_hp_targetinfo(unsigned long arg)
                hdr.PageNumber = 0;
                hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
 
-               cfg.hdr = &hdr;
+               cfg.cfghdr.hdr = &hdr;
                cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
                cfg.dir = 0;
                cfg.timeout = 0;
@@ -2677,15 +2679,15 @@ mptctl_hp_targetinfo(unsigned long arg)
        hdr.PageNumber = 3;
        hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
 
-       cfg.hdr = &hdr;
+       cfg.cfghdr.hdr = &hdr;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;
        cfg.timeout = 0;
        cfg.physAddr = -1;
-       if ((mpt_config(ioc, &cfg) == 0) && (cfg.hdr->PageLength > 0)) {
+       if ((mpt_config(ioc, &cfg) == 0) && (cfg.cfghdr.hdr->PageLength > 0)) {
                /* Issue the second config page request */
                cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-               data_sz = (int) cfg.hdr->PageLength * 4;
+               data_sz = (int) cfg.cfghdr.hdr->PageLength * 4;
                pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent(
                                                        ioc->pcidev, data_sz, &page_dma);
                if (pg3_alloc) {
@@ -2705,10 +2707,10 @@ mptctl_hp_targetinfo(unsigned long arg)
 
        /* Copy the data from kernel memory to user memory
         */
-       if (copy_to_user((char *)arg, &karg, sizeof(hp_target_info_t))) {
+       if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) {
                printk(KERN_ERR "%s@%d::mptctl_hp_target_info - "
                        "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
-                               __FILE__, __LINE__, (void*)uarg);
+                               __FILE__, __LINE__, uarg);
                return -EFAULT;
        }
 
@@ -2717,20 +2719,15 @@ mptctl_hp_targetinfo(unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51)
-#define        owner_THIS_MODULE  .owner = THIS_MODULE,
-#else
-#define        owner_THIS_MODULE
-#endif
-
 static struct file_operations mptctl_fops = {
-       owner_THIS_MODULE
+       .owner =        THIS_MODULE,
        .llseek =       no_llseek,
-       .read =         mptctl_read,
-       .write =        mptctl_write,
-       .ioctl =        mptctl_ioctl,
-       .open =         mptctl_open,
        .release =      mptctl_release,
+       .fasync =       mptctl_fasync,
+       .unlocked_ioctl = mptctl_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = compat_mpctl_ioctl,
+#endif
 };
 
 static struct miscdevice mptctl_miscdev = {
@@ -2743,31 +2740,9 @@ static struct miscdevice mptctl_miscdev = {
 
 #ifdef CONFIG_COMPAT
 
-#include <linux/ioctl32.h>
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* compat_XXX functions are used to provide a conversion between
- * pointers and u32's. If the arg does not contain any pointers, then
- * a specialized function (compat_XXX) is not needed. If the arg
- * does contain pointer(s), then the specialized function is used
- * to ensure the structure contents is properly processed by mptctl.
- */
 static int
-compat_mptctl_ioctl(unsigned int fd, unsigned int cmd,
-                       unsigned long arg, struct file *filp)
-{
-       int ret;
-
-       lock_kernel();
-       dctlprintk((KERN_INFO MYNAM "::compat_mptctl_ioctl() called\n"));
-       ret = mptctl_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
-       return ret;
-}
-static int
-compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
-                       unsigned long arg, struct file *filp)
+compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
+                       unsigned long arg)
 {
        struct mpt_fw_xfer32 kfw32;
        struct mpt_fw_xfer kfw;
@@ -2778,7 +2753,7 @@ compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
 
        dctlprintk((KERN_INFO MYNAM "::compat_mptfwxfer_ioctl() called\n"));
 
-       if (copy_from_user(&kfw32, (char *)arg, sizeof(kfw32)))
+       if (copy_from_user(&kfw32, (char __user *)arg, sizeof(kfw32)))
                return -EFAULT;
 
        /* Verify intended MPT adapter */
@@ -2795,21 +2770,21 @@ compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
 
        kfw.iocnum = iocnum;
        kfw.fwlen = kfw32.fwlen;
-       kfw.bufp = (void *)(unsigned long)kfw32.bufp;
+       kfw.bufp = compat_ptr(kfw32.bufp);
 
        ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
 
-       up(&mptctl_syscall_sem_ioc[iocp->id]);
+       mutex_unlock(&iocp->ioctl->ioctl_mutex);
 
        return ret;
 }
 
 static int
-compat_mpt_command(unsigned int fd, unsigned int cmd,
-                       unsigned long arg, struct file *filp)
+compat_mpt_command(struct file *filp, unsigned int cmd,
+                       unsigned long arg)
 {
        struct mpt_ioctl_command32 karg32;
-       struct mpt_ioctl_command32 *uarg = (struct mpt_ioctl_command32 *) arg;
+       struct mpt_ioctl_command32 __user *uarg = (struct mpt_ioctl_command32 __user *) arg;
        struct mpt_ioctl_command karg;
        MPT_ADAPTER *iocp = NULL;
        int iocnum, iocnumX;
@@ -2818,7 +2793,7 @@ compat_mpt_command(unsigned int fd, unsigned int cmd,
 
        dctlprintk((KERN_INFO MYNAM "::compat_mpt_command() called\n"));
 
-       if (copy_from_user(&karg32, (char *)arg, sizeof(karg32)))
+       if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32)))
                return -EFAULT;
 
        /* Verify intended MPT adapter */
@@ -2844,93 +2819,127 @@ compat_mpt_command(unsigned int fd, unsigned int cmd,
        karg.maxSenseBytes = karg32.maxSenseBytes;
        karg.dataSgeOffset = karg32.dataSgeOffset;
 
-       karg.replyFrameBufPtr = (char *)(unsigned long)karg32.replyFrameBufPtr;
-       karg.dataInBufPtr = (char *)(unsigned long)karg32.dataInBufPtr;
-       karg.dataOutBufPtr = (char *)(unsigned long)karg32.dataOutBufPtr;
-       karg.senseDataPtr = (char *)(unsigned long)karg32.senseDataPtr;
+       karg.replyFrameBufPtr = (char __user *)(unsigned long)karg32.replyFrameBufPtr;
+       karg.dataInBufPtr = (char __user *)(unsigned long)karg32.dataInBufPtr;
+       karg.dataOutBufPtr = (char __user *)(unsigned long)karg32.dataOutBufPtr;
+       karg.senseDataPtr = (char __user *)(unsigned long)karg32.senseDataPtr;
 
        /* Pass new structure to do_mpt_command
         */
-       ret = mptctl_do_mpt_command (karg, (char *) &uarg->MF, 0);
+       ret = mptctl_do_mpt_command (karg, &uarg->MF);
 
-       up(&mptctl_syscall_sem_ioc[iocp->id]);
+       mutex_unlock(&iocp->ioctl->ioctl_mutex);
 
        return ret;
 }
 
+static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+       long ret;
+       lock_kernel();
+       switch (cmd) {
+       case MPTIOCINFO:
+       case MPTIOCINFO1:
+       case MPTIOCINFO2:
+       case MPTTARGETINFO:
+       case MPTEVENTQUERY:
+       case MPTEVENTENABLE:
+       case MPTEVENTREPORT:
+       case MPTHARDRESET:
+       case HP_GETHOSTINFO:
+       case HP_GETTARGETINFO:
+       case MPTTEST:
+               ret = __mptctl_ioctl(f, cmd, arg);
+               break;
+       case MPTCOMMAND32:
+               ret = compat_mpt_command(f, cmd, arg);
+               break;
+       case MPTFWDOWNLOAD32:
+               ret = compat_mptfwxfer_ioctl(f, cmd, arg);
+               break;
+       default:
+               ret = -ENOIOCTLCMD;
+               break;
+       }
+       unlock_kernel();
+       return ret;
+}
+
 #endif
 
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-int __init mptctl_init(void)
+/*
+ *     mptctl_probe - Installs ioctl devices per bus.
+ *     @pdev: Pointer to pci_dev structure
+ *
+ *     Returns 0 for success, non-zero for failure.
+ *
+ */
+
+static int
+mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int err;
-       int i;
-       int where = 1;
        int sz;
        u8 *mem;
-       MPT_ADAPTER *ioc = NULL;
-       int iocnum;
+       MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 
-       show_mptmod_ver(my_NAME, my_VERSION);
+       /*
+        * Allocate and inite a MPT_IOCTL structure
+       */
+       sz = sizeof (MPT_IOCTL);
+       mem = kmalloc(sz, GFP_KERNEL);
+       if (mem == NULL) {
+               err = -ENOMEM;
+               goto out_fail;
+       }
 
-       for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-               sema_init(&mptctl_syscall_sem_ioc[i], 1);
+       memset(mem, 0, sz);
+       ioc->ioctl = (MPT_IOCTL *) mem;
+       ioc->ioctl->ioc = ioc;
+       mutex_init(&ioc->ioctl->ioctl_mutex);
+       return 0;
 
-               ioc = NULL;
-               if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-                   (ioc == NULL)) {
-                       continue;
-               }
-               else {
-                       /* This adapter instance is found.
-                        * Allocate and inite a MPT_IOCTL structure
-                        */
-                       sz = sizeof (MPT_IOCTL);
-                       mem = kmalloc(sz, GFP_KERNEL);
-                       if (mem == NULL) {
-                               err = -ENOMEM;
-                               goto out_fail;
-                       }
+out_fail:
 
-                       memset(mem, 0, sz);
-                       ioc->ioctl = (MPT_IOCTL *) mem;
-                       ioc->ioctl->ioc = ioc;
-                       init_timer (&ioc->ioctl->timer);
-                       ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
-                       ioc->ioctl->timer.function = mptctl_timer_expired;
-                       init_timer (&ioc->ioctl->TMtimer);
-                       ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
-                       ioc->ioctl->TMtimer.function = mptctl_timer_expired;
-               }
-       }
+       mptctl_remove(pdev);
+       return err;
+}
 
-#ifdef CONFIG_COMPAT
-       err = register_ioctl32_conversion(MPTIOCINFO, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(MPTIOCINFO1, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(MPTTARGETINFO, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(MPTTEST, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(MPTEVENTQUERY, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(MPTEVENTENABLE, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(MPTEVENTREPORT, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(MPTHARDRESET, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(MPTCOMMAND32, compat_mpt_command);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(MPTFWDOWNLOAD32,
-                                         compat_mptfwxfer_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(HP_GETHOSTINFO, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-       err = register_ioctl32_conversion(HP_GETTARGETINFO, compat_mptctl_ioctl);
-       if (++where && err) goto out_fail;
-#endif
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     mptctl_remove - Removed ioctl devices
+ *     @pdev: Pointer to pci_dev structure
+ *
+ *
+ */
+static void
+mptctl_remove(struct pci_dev *pdev)
+{
+       MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+
+       kfree ( ioc->ioctl );
+}
+
+static struct mpt_pci_driver mptctl_driver = {
+  .probe               = mptctl_probe,
+  .remove              = mptctl_remove,
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int __init mptctl_init(void)
+{
+       int err;
+       int where = 1;
+
+       show_mptmod_ver(my_NAME, my_VERSION);
+
+       if(mpt_device_driver_register(&mptctl_driver,
+         MPTCTL_DRIVER) != 0 ) {
+               dprintk((KERN_INFO MYNAM
+               ": failed to register dd callbacks\n"));
+       }
 
        /* Register this device */
        err = misc_register(&mptctl_miscdev);
@@ -2959,50 +2968,23 @@ int __init mptctl_init(void)
                /* FIXME! */
        }
 
+       if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) {
+               devtverboseprintk((KERN_INFO MYNAM
+                 ": Registered for IOC event notifications\n"));
+       }
+
        return 0;
 
 out_fail:
 
-#ifdef CONFIG_COMPAT
-       printk(KERN_ERR MYNAM ": ERROR: Failed to register ioctl32_conversion!"
-                       " (%d:err=%d)\n", where, err);
-       unregister_ioctl32_conversion(MPTIOCINFO);
-       unregister_ioctl32_conversion(MPTIOCINFO1);
-       unregister_ioctl32_conversion(MPTTARGETINFO);
-       unregister_ioctl32_conversion(MPTTEST);
-       unregister_ioctl32_conversion(MPTEVENTQUERY);
-       unregister_ioctl32_conversion(MPTEVENTENABLE);
-       unregister_ioctl32_conversion(MPTEVENTREPORT);
-       unregister_ioctl32_conversion(MPTHARDRESET);
-       unregister_ioctl32_conversion(MPTCOMMAND32);
-       unregister_ioctl32_conversion(MPTFWDOWNLOAD32);
-       unregister_ioctl32_conversion(HP_GETHOSTINFO);
-       unregister_ioctl32_conversion(HP_GETTARGETINFO);
-#endif
+       mpt_device_driver_deregister(MPTCTL_DRIVER);
 
-       for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-               ioc = NULL;
-               if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-                   (ioc == NULL)) {
-                       continue;
-               }
-               else {
-                       if (ioc->ioctl) {
-                               kfree ( ioc->ioctl );
-                               ioc->ioctl = NULL;
-                       }
-               }
-       }
        return err;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-void mptctl_exit(void)
+static void mptctl_exit(void)
 {
-       int i;
-       MPT_ADAPTER *ioc;
-       int iocnum;
-
        misc_deregister(&mptctl_miscdev);
        printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",
                         mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
@@ -3015,35 +2997,8 @@ void mptctl_exit(void)
        mpt_deregister(mptctl_id);
        printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n");
 
-#ifdef CONFIG_COMPAT
-       unregister_ioctl32_conversion(MPTIOCINFO);
-       unregister_ioctl32_conversion(MPTIOCINFO1);
-       unregister_ioctl32_conversion(MPTTARGETINFO);
-       unregister_ioctl32_conversion(MPTTEST);
-       unregister_ioctl32_conversion(MPTEVENTQUERY);
-       unregister_ioctl32_conversion(MPTEVENTENABLE);
-       unregister_ioctl32_conversion(MPTEVENTREPORT);
-       unregister_ioctl32_conversion(MPTHARDRESET);
-       unregister_ioctl32_conversion(MPTCOMMAND32);
-       unregister_ioctl32_conversion(MPTFWDOWNLOAD32);
-       unregister_ioctl32_conversion(HP_GETHOSTINFO);
-       unregister_ioctl32_conversion(HP_GETTARGETINFO);
-#endif
+        mpt_device_driver_deregister(MPTCTL_DRIVER);
 
-       /* Free allocated memory */
-       for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-               ioc = NULL;
-               if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-                   (ioc == NULL)) {
-                       continue;
-               }
-               else {
-                       if (ioc->ioctl) {
-                               kfree ( ioc->ioctl );
-                               ioc->ioctl = NULL;
-                       }
-               }
-       }
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/