[SCSI] mpt fusion: update MAINTAINERS (fusion part)
[safe/jmp/linux-2.6] / drivers / message / fusion / mptctl.c
index 70a812a..58e6c31 100644 (file)
@@ -4,8 +4,8 @@
  *      For use with LSI Logic PCI chip/adapters
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -66,7 +66,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 
-#define COPYRIGHT      "Copyright (c) 1999-2005 LSI Logic Corporation"
+#define COPYRIGHT      "Copyright (c) 1999-2007 LSI Logic Corporation"
 #define MODULEAUTHOR   "LSI Logic Corporation"
 #include "mptbase.h"
 #include "mptctl.h"
@@ -79,6 +79,7 @@
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
@@ -136,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...
@@ -306,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
                 */
                dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
                         ioctl->ioc->name));
-               mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
+               mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
        }
        return;
 
@@ -354,7 +361,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
                        ioctl->ioc->name, mf));
 
        pScsiTm = (SCSITaskMgmt_t *) mf;
-       pScsiTm->TargetID = ioctl->target;
+       pScsiTm->TargetID = ioctl->id;
        pScsiTm->Bus = hd->port;        /* 0 */
        pScsiTm->ChainOffset = 0;
        pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
@@ -385,18 +392,18 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
        }
 
        /* Now wait for the command to complete */
-       ii = wait_event_interruptible_timeout(mptctl_wait,
+       ii = wait_event_timeout(mptctl_wait,
             ioctl->wait_done == 1,
             HZ*5 /* 5 second timeout */);
 
        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:
 
-       mpt_free_msg_frame(hd->ioc, mf);
        mptctl_free_tm_flags(ioctl->ioc);
        return retval;
 }
@@ -472,6 +479,69 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* ASYNC Event Notification Support */
+static int
+mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+{
+       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;
+}
+
+static int
+mptctl_fasync(int fd, struct file *filep, int mode)
+{
+       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 int
+mptctl_release(struct inode *inode, struct file *filep)
+{
+       dctlprintk(("%s() called\n", __FUNCTION__));
+       return fasync_helper(-1, filep, 0, &async_queue);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  MPT ioctl handler
  *  cmd - specify the particular IOCTL command to be issued
@@ -674,22 +744,23 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
        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, iocp)) == 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);
@@ -702,7 +773,11 @@ mptctl_do_fw_download(int ioc, char __user *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.
         */
@@ -754,7 +829,7 @@ mptctl_do_fw_download(int ioc, char __user *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,
@@ -803,11 +878,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
        /*
         * Finally, perform firmware download.
         */
-       iocp->ioctl->wait_done = 0;
+       ReplyMsg = NULL;
        mpt_put_msg_frame(mptctl_id, iocp, mf);
 
        /* Now wait for the command to complete */
-       ret = wait_event_interruptible_timeout(mptctl_wait,
+       ret = wait_event_timeout(mptctl_wait,
             iocp->ioctl->wait_done == 1,
             HZ*60);
 
@@ -1084,15 +1159,12 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
        struct mpt_ioctl_iocinfo *karg;
        MPT_ADAPTER             *ioc;
        struct pci_dev          *pdev;
-       struct Scsi_Host        *sh;
-       MPT_SCSI_HOST           *hd;
        int                     iocnum;
-       int                     numDevices = 0;
-       unsigned int            max_id;
-       int                     ii;
        unsigned int            port;
        int                     cim_rev;
        u8                      revision;
+       struct scsi_device      *sdev;
+       VirtDevice              *vdev;
 
        dctlprintk((": mptctl_getiocinfo called.\n"));
        /* Add of PCI INFO results in unaligned access for
@@ -1145,7 +1217,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
        /* Fill in the data and return the structure to the calling
         * program
         */
-       if (ioc->bus_type == 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;
@@ -1170,34 +1244,26 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
                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 
+               /* 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.u.bits.functionNumber = PCI_FUNC( pdev->devfn );
                karg->pciInfo.segmentID = pci_domain_nr(pdev->bus);
        }
 
        /* Get number of devices
          */
-       if ((sh = ioc->sh) != NULL) {
-                /* sh->max_id = maximum target ID + 1
-                */
-               max_id = sh->max_id - 1;
-               hd = (MPT_SCSI_HOST *) sh->hostdata;
-
-               /* Check all of the target structures and
-                * keep a counter.
-                */
-               if (hd && hd->Targets) {
-                       for (ii = 0; ii <= max_id; ii++) {
-                               if (hd->Targets[ii])
-                                       numDevices++;
-                       }
+       karg->numDevices = 0;
+       if (ioc->sh) {
+               shost_for_each_device(sdev, ioc->sh) {
+                       vdev = sdev->hostdata;
+                       if (vdev->vtarget->tflags &
+                           MPT_TARGET_FLAGS_RAID_COMPONENT)
+                               continue;
+                       karg->numDevices++;
                }
        }
-       karg->numDevices = numDevices;
 
        /* Set the BIOS and FW Version
         */
@@ -1243,21 +1309,16 @@ mptctl_gettargetinfo (unsigned long 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;
-       VirtTarget              *vdev;
+       VirtDevice              *vdev;
        char                    *pmem;
        int                     *pdata;
-       IOCPage2_t              *pIoc2;
-       IOCPage3_t              *pIoc3;
        int                     iocnum;
        int                     numDevices = 0;
-       unsigned int            max_id;
-       int                     id, jj, indexed_lun, lun_index;
-       u32                     lun;
+       int                     lun;
        int                     maxWordsLeft;
        int                     numBytes;
-       u8                      port, devType, bus_id;
+       u8                      port;
+       struct scsi_device      *sdev;
 
        dctlprintk(("mptctl_gettargetinfo called.\n"));
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
@@ -1313,74 +1374,22 @@ mptctl_gettargetinfo (unsigned long arg)
 
        /* Get number of devices
          */
-       if ((sh = ioc->sh) != NULL) {
-
-               max_id = sh->max_id - 1;
-               hd = (MPT_SCSI_HOST *) sh->hostdata;
-
-               /* Check all of the target structures.
-                * Save the Id and increment the counter,
-                * if ptr non-null.
-                * sh->max_id = maximum target ID + 1
-                */
-               if (hd && hd->Targets) {
-                       mpt_findImVolumes(ioc);
-                       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 - "
-               "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
-                                               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++;
-                       }
+       if (ioc->sh){
+               shost_for_each_device(sdev, ioc->sh) {
+                       if (!maxWordsLeft)
+                               continue;
+                       vdev = sdev->hostdata;
+                       if (vdev->vtarget->tflags &
+                           MPT_TARGET_FLAGS_RAID_COMPONENT)
+                               continue;
+                       lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun;
+                       *pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) +
+                           (vdev->vtarget->id ));
+                       pdata++;
+                       numDevices++;
+                       --maxWordsLeft;
                }
        }
-data_space_full:
        karg.numDevices = numDevices;
 
        /* Copy part of the data from kernel memory to user memory
@@ -1500,7 +1509,7 @@ 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
@@ -1550,7 +1559,6 @@ mptctl_eventenable (unsigned long arg)
                memset(ioc->events, 0, sz);
                ioc->alloc_total += sz;
 
-               ioc->eventLogSize = MPTCTL_EVENT_LOG_SIZE;
                ioc->eventContext = 0;
         }
 
@@ -1590,7 +1598,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.
@@ -1598,6 +1606,9 @@ 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);
@@ -1743,6 +1754,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
        int             msgContext;
        u16             req_idx;
        ulong           timeout;
+       struct scsi_device *sdev;
 
        dctlprintk(("mptctl_do_mpt_command called.\n"));
        bufIn.kptr = bufOut.kptr = NULL;
@@ -1824,14 +1836,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
        case MPI_FUNCTION_SCSI_IO_REQUEST:
                if (ioc->sh) {
                        SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
-                       VirtTarget      *pTarget = NULL;
-                       MPT_SCSI_HOST   *hd = NULL;
                        int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
                        int scsidir = 0;
-                       int target = (int) pScsiReq->TargetID;
                        int dataSize;
+                       u32 id;
 
-                       if ((target < 0) || (target >= ioc->sh->max_id)) {
+                       id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus;
+                       if (pScsiReq->TargetID > id) {
                                printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
                                        "Target ID out of bounds. \n",
                                        __FILE__, __LINE__);
@@ -1839,7 +1850,17 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                                goto done_free_mem;
                        }
 
-                       pScsiReq->MsgFlags = mpt_msg_flags();
+                       if (pScsiReq->Bus >= ioc->number_of_buses) {
+                               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                                       "Target Bus out of bounds. \n",
+                                       __FILE__, __LINE__);
+                               rc = -ENODEV;
+                               goto done_free_mem;
+                       }
+
+                       pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
+                       pScsiReq->MsgFlags |= mpt_msg_flags();
+
 
                        /* verify that app has not requested
                         *      more sense data than driver
@@ -1856,13 +1877,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                                cpu_to_le32(ioc->sense_buf_low_dma
                                   + (req_idx * MPT_SENSE_BUFFER_ALLOC));
 
-                       if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) {
-                               if (hd->Targets)
-                                       pTarget = hd->Targets[target];
-                       }
+                       shost_for_each_device(sdev, ioc->sh) {
+                               struct scsi_target *starget = scsi_target(sdev);
+                               VirtTarget *vtarget = starget->hostdata;
 
-                       if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
-                               qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+                               if ((pScsiReq->TargetID == vtarget->id) &&
+                                   (pScsiReq->Bus == vtarget->channel) &&
+                                   (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+                                       qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+                       }
 
                        /* Have the IOCTL driver set the direction based
                         * on the dataOutSize (ordering issue with Sparc).
@@ -1879,7 +1902,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                        pScsiReq->DataLength = cpu_to_le32(dataSize);
 
                        ioc->ioctl->reset = MPTCTL_RESET_OK;
-                       ioc->ioctl->target = target;
+                       ioc->ioctl->id = pScsiReq->TargetID;
 
                } else {
                        printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
@@ -1921,7 +1944,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                        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
@@ -1956,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                        pScsiReq->DataLength = cpu_to_le32(dataSize);
 
                        ioc->ioctl->reset = MPTCTL_RESET_OK;
-                       ioc->ioctl->target = pScsiReq->TargetID;
+                       ioc->ioctl->id = pScsiReq->TargetID;
                } else {
                        printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
                                "SCSI driver is not loaded. \n",
@@ -2151,7 +2176,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 
        /* Now wait for the command to complete */
        timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
-       timeout = wait_event_interruptible_timeout(mptctl_wait,
+       timeout = wait_event_timeout(mptctl_wait,
             ioc->ioctl->wait_done == 1,
             HZ*timeout);
 
@@ -2251,7 +2276,7 @@ done_free_mem:
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Prototype Routine for the HP HOST INFO command.
+/* Prototype Routine for the HOST INFO command.
  *
  * Outputs:    None.
  * Return:     0 if successful
@@ -2267,13 +2292,16 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
        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
@@ -2391,7 +2419,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 
        karg.base_io_addr = pci_resource_start(pdev, 0);
 
-       if (ioc->bus_type == FC)
+       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;
@@ -2409,20 +2437,67 @@ 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;
-               }
-               pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
-               pbuf = NULL;
+       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);
+
        /* Copy the data from kernel memory to user memory
         */
        if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
@@ -2437,7 +2512,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
@@ -2480,7 +2555,7 @@ mptctl_hp_targetinfo(unsigned long arg)
 
        /*  There is nothing to do for FCP parts.
         */
-       if (ioc->bus_type == FC)
+       if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
                return 0;
 
        if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL))
@@ -2587,9 +2662,11 @@ mptctl_hp_targetinfo(unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-static struct file_operations mptctl_fops = {
+static const struct file_operations mptctl_fops = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
+       .release =      mptctl_release,
+       .fasync =       mptctl_fasync,
        .unlocked_ioctl = mptctl_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl = compat_mpctl_ioctl,
@@ -2834,6 +2911,11 @@ static 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: