Whamcloud - gitweb
Branch HEAD
authorjohann <johann>
Fri, 22 Feb 2008 18:28:21 +0000 (18:28 +0000)
committerjohann <johann>
Fri, 22 Feb 2008 18:28:21 +0000 (18:28 +0000)
b=14618

A performance regression has been discovered in the MPT Fusion
driver between versions 3.02.73rh and 3.02.99.00rh. As a
consequence, we have downgraded the MPT Fusion driver in the RHEL4
kernel from 3.02.99.00 to 3.02.73 until this problem is fixed.

lustre/ChangeLog
lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch [new file with mode: 0644]
lustre/kernel_patches/series/2.6-rhel4.series

index ffe4380..f484991 100644 (file)
@@ -746,6 +746,15 @@ Severity   : normal
 Bugzilla   : 14864
 Description: better handle error messages in extents code
 
+Severity   : normal
+Frequency  : RHEL4 only
+Bugzilla   : 14618
+Description: mkfs is very slow on IA64/RHEL4
+Details    : A performance regression has been discovered in the MPT Fusion
+            driver between versions 3.02.73rh and 3.02.99.00rh. As a
+            consequence, we have downgraded the MPT Fusion driver in the RHEL4
+            kernel from 3.02.99.00 to 3.02.73 until this problem is fixed.
+
 --------------------------------------------------------------------------------
 
 2007-08-10         Cluster File Systems, Inc. <info@clusterfs.com>
diff --git a/lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch b/lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch
new file mode 100644 (file)
index 0000000..7bb3440
--- /dev/null
@@ -0,0 +1,27949 @@
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.c linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.c   2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.c  1970-01-01 01:00:00.000000000 +0100
+@@ -1,5894 +0,0 @@
+-#define MPT_CSMI_DESCRIPTION "LSI Logic Corporation: Fusion MPT Driver "MPT_LINUX_VERSION_COMMON
+-#define csmisas_is_this_sas_cntr(ioc) (ioc->bus_type == SAS) ? 1 : 0
+-
+-static int csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus,
+-    u8 VolumeId, pMpiRaidActionReply_t reply);
+-static u8  map_sas_status_to_csmi(u8 mpi_sas_status);
+-
+-/**
+- * reverse_byte_order64
+- *
+- * @data64
+- *
+- **/
+-static u64
+-reverse_byte_order64(u64 data64)
+-{
+-      int i;
+-      u64 rc;
+-      u8  *inWord = (u8*)&data64, *outWord = (u8*)&rc;
+-
+-      for (i = 0 ; i < 8 ; i++)
+-              outWord[i] = inWord[7-i];
+-
+-      return rc;
+-}
+-
+-/**
+- * csmisas_is_sata
+- *
+- * @phys_disk
+- *
+- **/
+-static int
+-csmisas_is_sata(RaidPhysDiskPage0_t *phys_disk)
+-{
+-      if ((phys_disk->ExtDiskIdentifier[0] == 'A') &&
+-          (phys_disk->ExtDiskIdentifier[1] == 'T') &&
+-          (phys_disk->ExtDiskIdentifier[2] == 'A'))
+-              return 1;
+-      else
+-              return 0;
+-}
+-
+-/**
+- * csmisas_is_end_device
+- *
+- * @attached
+- *
+- **/
+-static inline int
+-csmisas_is_end_device(struct mptsas_devinfo * attached)
+-{
+-      if ((attached->sas_address) &&
+-          (attached->device_info &
+-          MPI_SAS_DEVICE_INFO_END_DEVICE) &&
+-          ((attached->device_info &
+-          MPI_SAS_DEVICE_INFO_SSP_TARGET) |
+-          (attached->device_info &
+-          MPI_SAS_DEVICE_INFO_STP_TARGET) |
+-          (attached->device_info &
+-          MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
+-              return 1;
+-      else
+-              return 0;
+-}
+-
+-/**
+- * csmisas_is_phys_disk
+- *
+- * returns (1) success (0) fail - not a phys disk
+- **/
+-int
+-csmisas_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id)
+-{
+-      struct inactive_raid_component_info *component_info;
+-      int i;
+-      int rc = 0;
+-
+-      if (!ioc->raid_data.pIocPg3)
+-              goto out;
+-      for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+-              if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+-                  (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+-                      rc = 1;
+-                      goto out;
+-              }
+-      }
+-
+-      /*
+-       * Check inactive list for matching phys disks
+-       */
+-      if (list_empty(&ioc->raid_data.inactive_list))
+-              goto out;
+-
+-      down(&ioc->raid_data.inactive_list_mutex);
+-      list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+-          list) {
+-              if ((component_info->d.PhysDiskID == id) &&
+-                  (component_info->d.PhysDiskBus == channel))
+-                      rc = 1;
+-      }
+-      up(&ioc->raid_data.inactive_list_mutex);
+-
+- out:
+-      return rc;
+-}
+-
+-/**
+- * csmisas_raid_id_to_num
+- *
+- * Obtains the phys disk num for given H:C:T nexus
+- *
+- * input (channel/id)
+- * output (phys disk number - used by SCSI_IO_PASSTHRU to access hidden component)
+- *
+- * returns - signed return means failure
+- **/
+-s8
+-csmisas_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-      struct inactive_raid_component_info *component_info;
+-      int i;
+-      s8 rc = -ENXIO;
+-
+-      if (!ioc->raid_data.pIocPg3)
+-              goto out;
+-      for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+-              if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+-                  (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+-                      rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
+-                      goto out;
+-              }
+-      }
+-
+-      /*
+-       * Check inactive list for matching phys disks
+-       */
+-      if (list_empty(&ioc->raid_data.inactive_list))
+-              goto out;
+-
+-      down(&ioc->raid_data.inactive_list_mutex);
+-      list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+-          list) {
+-              if ((component_info->d.PhysDiskID == id) &&
+-                  (component_info->d.PhysDiskBus == channel))
+-                      rc = component_info->d.PhysDiskNum;
+-      }
+-      up(&ioc->raid_data.inactive_list_mutex);
+-
+- out:
+-      return rc;
+-}
+-
+-/**
+- * csmisas_get_device_component_by_os
+- *
+- * Obtain device component object by operating system mapping
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static struct sas_device_info *
+-csmisas_get_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-      struct sas_device_info *sas_info, *p;
+-
+-      sas_info = NULL;
+-
+-      down(&ioc->sas_device_info_mutex);
+-      list_for_each_entry(p, &ioc->sas_device_info_list, list) {
+-              if (p->os.channel == channel && p->os.id == id) {
+-                      sas_info = p;
+-                      goto out;
+-              }
+-      }
+-
+- out:
+-      up(&ioc->sas_device_info_mutex);
+-      return sas_info;
+-}
+-
+-/**
+- * csmisas_get_device_component
+- *
+- * Obtain device component object by firmware system mapping
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static struct sas_device_info *
+-csmisas_get_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-      struct sas_device_info *sas_info, *p;
+-
+-      sas_info = NULL;
+-
+-      down(&ioc->sas_device_info_mutex);
+-      list_for_each_entry(p, &ioc->sas_device_info_list, list) {
+-              if (p->fw.channel == channel && p->fw.id == id) {
+-                      sas_info = p;
+-                      goto out;
+-              }
+-      }
+-
+- out:
+-      up(&ioc->sas_device_info_mutex);
+-      return sas_info;
+-}
+-
+-
+-/**
+- * csmisas_get_device_component_by_sas_addr
+- *
+- * Obtain device component object by sas address
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static struct sas_device_info *
+-csmisas_get_device_component_by_sas_addr(MPT_ADAPTER *ioc, u64 sas_address)
+-{
+-      struct sas_device_info *sas_info, *p;
+-
+-      sas_info = NULL;
+-
+-      down(&ioc->sas_device_info_mutex);
+-      list_for_each_entry(p, &ioc->sas_device_info_list, list) {
+-              dcsmisasprintk((KERN_ERR
+-                  ":%s()"
+-                  " looking for SASAddress=%llX entry SASAddress=%llX\n",
+-                  __FUNCTION__, sas_address, p->sas_address));
+-              if (p->sas_address == sas_address) {
+-                      sas_info = p;
+-                      dcsmisasprintk((KERN_ERR
+-                              ":%s()"
+-                              " found SASAddress=%llX\n",
+-                              __FUNCTION__, sas_address));
+-                      goto out;
+-              }
+-      }
+-
+- out:
+-      up(&ioc->sas_device_info_mutex);
+-      return sas_info;
+-}
+-
+-/**
+- * csmisas_send_command_wait
+- *
+- * Send mf to firmware
+- *
+- * @ioc
+- * @mf
+- * @timeout - timeout
+- *
+- *    Return: 0 for success
+- *    non-zero, failure
+- **/
+-static int
+-csmisas_send_command_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, int timeout)
+-{
+-      int rc;
+-      int mf_timeout;
+-
+-      mf_timeout = max_t(int, MPT_IOCTL_DEFAULT_TIMEOUT, timeout);
+-      INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-      ioc->ioctl->wait_done = 0;
+-      rc = 0;
+-
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+-      ioc->ioctl->timer.expires = jiffies + (MPT_JIFFY * mf_timeout);
+-      ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE;
+-      ADD_TIMER(&ioc->ioctl->timer);
+-#endif
+-
+-      mpt_put_msg_frame(mptctl_id, ioc, mf);
+-
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+-      WAIT_EVENT(mptctl_wait, ioc->ioctl->wait_done);
+-#else
+-      if ((wait_event_timeout(mptctl_wait,
+-          ioc->ioctl->wait_done == 1, HZ * mf_timeout) <=0) &&
+-          ioc->ioctl->wait_done != 1 ) {
+-              mpt_free_msg_frame(ioc, mf);
+-              mptctl_timeout_expired(ioc->ioctl);
+-              rc = -1;
+-      }
+-#endif
+-
+-      if (rc != 0)
+-              dfailprintk((KERN_ERR "%s@%d::%s() - "
+-                  "%s IOCTL timeout (%d)\n",
+-                  __FILE__, __LINE__, __FUNCTION__,
+-                  ioc->name, mf_timeout));
+-
+-      return rc;
+-}
+-
+-/**
+- * csmisas_send_handshake_wait
+- *
+- * Handshake a mf to firmware
+- *
+- * @ioc
+- * @mf
+- * @mf_size
+- * @timeout - timeout
+- *
+- *    Return: 0 for success
+- *    non-zero, failure
+- **/
+-static int
+-csmisas_send_handshake_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, int timeout)
+-{
+-      int rc;
+-      int mf_timeout;
+-
+-      mf_timeout = max_t(int, MPT_IOCTL_DEFAULT_TIMEOUT, timeout);
+-      INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-      ioc->ioctl->wait_done = 0;
+-      rc = 0;
+-
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+-      ioc->ioctl->timer.expires = jiffies + (MPT_JIFFY * mf_timeout);
+-      ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE;
+-      ADD_TIMER(&ioc->ioctl->timer);
+-#endif
+-
+-      rc = mpt_send_handshake_request(mptctl_id, ioc,
+-          sizeof(SCSITaskMgmt_t), (u32*)mf,timeout, CAN_SLEEP);
+-      if (rc != 0)
+-              return rc;
+-
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+-      WAIT_EVENT(mptctl_wait, ioc->ioctl->wait_done);
+-#else
+-      if ((wait_event_timeout(mptctl_wait,
+-          ioc->ioctl->wait_done == 1, HZ * mf_timeout) <=0) &&
+-          ioc->ioctl->wait_done != 1 ) {
+-              mpt_free_msg_frame(ioc, mf);
+-              mptctl_timeout_expired(ioc->ioctl);
+-              rc = -1;
+-      }
+-#endif
+-
+-      if (rc != 0)
+-              dfailprintk((KERN_ERR "%s@%d::%s() - "
+-                  "%s IOCTL timeout (%d)\n", __FILE__, __LINE__,
+-                  __FUNCTION__, ioc->name, mf_timeout));
+-
+-      return rc;
+-}
+-
+-/**
+- *    csmisas_get_manufacture_pg0 - Manufacturing Page 0.
+- *    @ioc: Pointer to MPT_ADAPTER structure
+- *    @mfgPage0: read only info set at manufacturing time
+- *
+- *    Return: 0 for success
+- *    -ENOMEM if no memory available
+- *            -EPERM if not allowed due to ISR context
+- *            -EAGAIN if no msg frames currently available
+- *            -EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-csmisas_get_manufacture_pg0(MPT_ADAPTER *ioc, ManufacturingPage0_t *mfgPage0)
+-{
+-
+-      ConfigPageHeader_t       hdr;
+-      CONFIGPARMS              cfg;
+-      ManufacturingPage0_t     *buffer = NULL;
+-      dma_addr_t               dma_handle;
+-      int                      data_sz;
+-      int                      rc;
+-
+-      /*
+-       * Get Manufacturing Page 0 header
+-       */
+-      data_sz = 0;
+-      hdr.PageVersion = MPI_MANUFACTURING0_PAGEVERSION;
+-      hdr.PageLength = 0;
+-      hdr.PageNumber = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
+-      cfg.cfghdr.hdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;
+-      cfg.pageAddr = 0;
+-      cfg.timeout = 0;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto get_manufacture_pg0_out;
+-
+-      if (hdr.PageLength == 0) {
+-              rc = -EFAULT;
+-              goto get_manufacture_pg0_out;
+-      }
+-
+-      data_sz = hdr.PageLength * 4;
+-      buffer = (ManufacturingPage0_t *) pci_alloc_consistent(ioc->pcidev,
+-              data_sz, &dma_handle);
+-      if (!buffer) {
+-              rc = -ENOMEM;
+-              goto get_manufacture_pg0_out;
+-      }
+-
+-      memset((u8 *)buffer, 0, data_sz);
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto get_manufacture_pg0_out;
+-
+-      strncpy(mfgPage0->ChipName, buffer->ChipName, 16);
+-      strncpy(mfgPage0->ChipRevision, buffer->ChipRevision, 8);
+-      strncpy(mfgPage0->BoardName, buffer->BoardName, 16);
+-      strncpy(mfgPage0->BoardAssembly, buffer->BoardAssembly, 16);
+-      strncpy(mfgPage0->BoardTracerNumber, buffer->BoardTracerNumber, 16);
+-
+-      dcsmisasprintk(("ChipName=%s\n",buffer->ChipName));
+-      dcsmisasprintk(("ChipRevision=%s\n",buffer->ChipRevision));
+-      dcsmisasprintk(("BoardName=%s\n",buffer->BoardName));
+-      dcsmisasprintk(("BoardAssembly=%s\n",buffer->BoardAssembly));
+-      dcsmisasprintk(("BoardTracerNumber=%s\n",buffer->BoardTracerNumber));
+-
+- get_manufacture_pg0_out:
+-
+-      if (buffer)
+-              pci_free_consistent(ioc->pcidev, data_sz,
+-                  (u8 *) buffer, dma_handle);
+-
+-
+-      return rc;
+-}
+-
+-/**
+- *    csmisas_get_number_hotspares - returns num hot spares in this ioc
+- *    @ioc: Pointer to MPT_ADAPTER structure
+- *
+- *    Return: number of hotspares
+- *
+- **/
+-static int
+-csmisas_get_number_hotspares(MPT_ADAPTER *ioc)
+-{
+-      ConfigPageHeader_t       hdr;
+-      CONFIGPARMS              cfg;
+-      IOCPage5_t               *buffer = NULL;
+-      dma_addr_t               dma_handle;
+-      int                      data_sz;
+-      int                      rc;
+-
+-      memset(&hdr, 0, sizeof(ConfigPageHeader_t));
+-      memset(&cfg, 0, sizeof(CONFIGPARMS));
+-
+-      rc = 0;
+-      data_sz = 0;
+-      hdr.PageNumber = 5;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-      cfg.cfghdr.hdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if (mpt_config(ioc, &cfg) != 0)
+-              goto get_ioc_pg5;
+-
+-      if (hdr.PageLength == 0)
+-              goto get_ioc_pg5;
+-
+-      data_sz = hdr.PageLength * 4;
+-      buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
+-              data_sz, &dma_handle);
+-      if (!buffer)
+-              goto get_ioc_pg5;
+-
+-      memset((u8 *)buffer, 0, data_sz);
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if (mpt_config(ioc, &cfg) != 0)
+-              goto get_ioc_pg5;
+-
+-      rc = buffer->NumHotSpares;
+-
+- get_ioc_pg5:
+-
+-      if (buffer)
+-              pci_free_consistent(ioc->pcidev, data_sz,
+-                  (u8 *) buffer, dma_handle);
+-
+-      return rc;
+-}
+-
+-
+-/**
+- *    csmisas_get_ioc_pg5 - ioc Page 5 hot spares
+- *    @ioc: Pointer to MPT_ADAPTER structure
+- *    @pIocPage5: ioc page 5
+- *    @data_size: expected data size(units=bytes)
+- *
+- *    Return: 0 for success
+- *    -ENOMEM if no memory available
+- *            -EPERM if not allowed due to ISR context
+- *            -EAGAIN if no msg frames currently available
+- *            -EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-csmisas_get_ioc_pg5(MPT_ADAPTER *ioc, IOCPage5_t *iocPage5, int data_size)
+-{
+-      ConfigPageHeader_t       hdr;
+-      CONFIGPARMS              cfg;
+-      IOCPage5_t               *buffer = NULL;
+-      dma_addr_t               dma_handle;
+-      int                      data_sz;
+-      int                      rc;
+-
+-      memset(&hdr, 0, sizeof(ConfigPageHeader_t));
+-      memset(&cfg, 0, sizeof(CONFIGPARMS));
+-
+-      rc = 0;
+-      data_sz = 0;
+-      hdr.PageNumber = 5;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-      cfg.cfghdr.hdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto get_ioc_pg5;
+-
+-      if (hdr.PageLength == 0) {
+-              rc = -EFAULT;
+-              goto get_ioc_pg5;
+-      }
+-
+-      data_sz = hdr.PageLength * 4;
+-      buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
+-              data_sz, &dma_handle);
+-      if (!buffer) {
+-              rc = -ENOMEM;
+-              goto get_ioc_pg5;
+-      }
+-
+-      memset((u8 *)buffer, 0, data_sz);
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto get_ioc_pg5;
+-
+-      memcpy(iocPage5, buffer, data_size);
+-
+- get_ioc_pg5:
+-
+-      if (buffer)
+-              pci_free_consistent(ioc->pcidev, data_sz,
+-                  (u8 *) buffer, dma_handle);
+-
+-      return rc;
+-}
+-
+-/**
+- *    csmisas_sas_device_pg0 - sas device page 0
+- *    @ioc: Pointer to MPT_ADAPTER structure
+- *    @mptsas_devinfo: structure found in mptsas.h
+- *    @form, @form_specific - defines the Page Address field in the config page
+- *            (pls refer to chapter 5.1 in the mpi spec)
+- *
+- *    Return: 0 for success
+- *    -ENOMEM if no memory available
+- *            -EPERM if not allowed due to ISR context
+- *            -EAGAIN if no msg frames currently available
+- *            -EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-csmisas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
+-              u32 form, u32 form_specific)
+-{
+-      ConfigExtendedPageHeader_t hdr;
+-      CONFIGPARMS cfg;
+-      SasDevicePage0_t *buffer;
+-      dma_addr_t dma_handle;
+-      u64 sas_address;
+-      int rc;
+-
+-      rc = 0;
+-      hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 0;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.pageAddr = form + form_specific;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = 10;
+-
+-      memset(device_info, 0, sizeof(struct mptsas_devinfo));
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto out;
+-
+-      if (!hdr.ExtPageLength) {
+-              rc = -ENXIO;
+-              goto out;
+-      }
+-
+-      buffer = pci_alloc_consistent(ioc->pcidev,
+-          hdr.ExtPageLength * 4, &dma_handle);
+-      if (!buffer) {
+-              rc = -ENOMEM;
+-              goto out;
+-      }
+-
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto out_free_consistent;
+-
+-      device_info->handle = le16_to_cpu(buffer->DevHandle);
+-      device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
+-      device_info->handle_enclosure =
+-          le16_to_cpu(buffer->EnclosureHandle);
+-      device_info->slot = le16_to_cpu(buffer->Slot);
+-      device_info->phy_id = buffer->PhyNum;
+-      device_info->port_id = buffer->PhysicalPort;
+-      device_info->id = buffer->TargetID;
+-      device_info->channel = buffer->Bus;
+-      memcpy(&sas_address, &buffer->SASAddress, sizeof(u64));
+-      device_info->sas_address = le64_to_cpu(sas_address);
+-      device_info->device_info =
+-          le32_to_cpu(buffer->DeviceInfo);
+-
+- out_free_consistent:
+-      pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-                          buffer, dma_handle);
+- out:
+-      return rc;
+-}
+-
+-/**
+- * Routine for the CSMI Sas Get Driver Info command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_driver_info(unsigned long arg)
+-{
+-
+-      CSMI_SAS_DRIVER_INFO_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_DRIVER_INFO_BUFFER     karg;
+-      MPT_ADAPTER     *ioc = NULL;
+-      int             iocnum;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-            "Unable to read in csmi_sas_get_driver_info_buffer struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      /* Fill in the data and return the structure to the calling
+-       * program
+-       */
+-      memcpy( karg.Information.szName, MPT_MISCDEV_BASENAME,
+-          sizeof(MPT_MISCDEV_BASENAME));
+-      memcpy( karg.Information.szDescription, MPT_CSMI_DESCRIPTION,
+-          sizeof(MPT_CSMI_DESCRIPTION));
+-
+-      karg.Information.usMajorRevision = MPT_LINUX_MAJOR_VERSION;
+-      karg.Information.usMinorRevision = MPT_LINUX_MINOR_VERSION;
+-      karg.Information.usBuildRevision = MPT_LINUX_BUILD_VERSION;
+-      karg.Information.usReleaseRevision = MPT_LINUX_RELEASE_VERSION;
+-
+-      karg.Information.usCSMIMajorRevision = CSMI_MAJOR_REVISION;
+-      karg.Information.usCSMIMinorRevision = CSMI_MINOR_REVISION;
+-
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-              sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-                 "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI_SAS_GET_CNTLR_CONFIG command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_cntlr_config(unsigned long arg)
+-{
+-
+-      CSMI_SAS_CNTLR_CONFIG_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_CNTLR_CONFIG_BUFFER    karg;
+-      MPT_ADAPTER     *ioc = NULL;
+-      int             iocnum;
+-      int             ii,msize,psize;
+-      unsigned int    reg;
+-      u32             l;
+-      ManufacturingPage0_t mfgPage0;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_CONFIG_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-           "Unable to read in csmi_sas_get_cntlr_config_buffer struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-            "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      /* Clear the struct before filling in data. */
+-      memset( &karg.Configuration, 0, sizeof(CSMI_SAS_CNTLR_CONFIG));
+-
+-      /* Fill in the data and return the structure to the calling
+-       * program
+-       */
+-
+-      /* Get Base IO and Mem Mapped Addresses. */
+-msize = psize = 0;
+-for(ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
+-              reg = PCI_BASE_ADDRESS_0 + (ii << 2);
+-              pci_read_config_dword(ioc->pcidev, reg, &l);
+-
+-              if ((l & PCI_BASE_ADDRESS_SPACE) ==
+-                       PCI_BASE_ADDRESS_SPACE_MEMORY) {
+-                  if(msize)
+-                         continue;
+-                  msize=1;
+-              karg.Configuration.BaseMemoryAddress.uLowPart =
+-                          l & PCI_BASE_ADDRESS_MEM_MASK;
+-
+-              if ((l & (PCI_BASE_ADDRESS_SPACE |
+-                   PCI_BASE_ADDRESS_MEM_TYPE_MASK))
+-                   == (PCI_BASE_ADDRESS_SPACE_MEMORY |
+-                   PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+-                     pci_read_config_dword(ioc->pcidev, reg+4, &l);
+-                     karg.Configuration.BaseMemoryAddress.uHighPart = l;
+-                  }
+-               }
+-
+-
+-                  else {
+-                      if(psize)
+-                       continue;
+-                       psize=1;
+-                      karg.Configuration.uBaseIoAddress =
+-                          l & PCI_BASE_ADDRESS_IO_MASK;
+-              }
+-
+-      }
+-
+-      karg.Configuration.uBoardID = (ioc->pcidev->subsystem_device << 16) |
+-          (ioc->pcidev->subsystem_vendor);
+-
+-      karg.Configuration.usSlotNumber =
+-          (ioc->pci_slot_number = 0xff) ?
+-          SLOT_NUMBER_UNKNOWN : ioc->pci_slot_number;
+-      karg.Configuration.bControllerClass = CSMI_SAS_CNTLR_CLASS_HBA;
+-      karg.Configuration.bIoBusType = CSMI_SAS_BUS_TYPE_PCI;
+-      karg.Configuration.BusAddress.PciAddress.bBusNumber =
+-          ioc->pcidev->bus->number;
+-      karg.Configuration.BusAddress.PciAddress.bDeviceNumber =
+-          PCI_SLOT(ioc->pcidev->devfn);
+-      karg.Configuration.BusAddress.PciAddress.bFunctionNumber =
+-          PCI_FUNC(ioc->pcidev->devfn);
+-      karg.Configuration.BusAddress.PciAddress.bReserved = 0;
+-      if (!csmisas_get_manufacture_pg0(ioc, &mfgPage0))
+-              memcpy( &karg.Configuration.szSerialNumber,
+-                  mfgPage0.BoardTracerNumber, 16 );
+-      karg.Configuration.usMajorRevision = ioc->facts.FWVersion.Struct.Major;
+-      karg.Configuration.usMinorRevision = ioc->facts.FWVersion.Struct.Minor;
+-      karg.Configuration.usBuildRevision = ioc->facts.FWVersion.Struct.Unit;
+-      karg.Configuration.usReleaseRevision = ioc->facts.FWVersion.Struct.Dev;
+-      karg.Configuration.usBIOSMajorRevision =
+-          (ioc->biosVersion & 0xFF000000) >> 24;
+-      karg.Configuration.usBIOSMinorRevision =
+-          (ioc->biosVersion & 0x00FF0000) >> 16;
+-      karg.Configuration.usBIOSBuildRevision =
+-          (ioc->biosVersion & 0x0000FF00) >> 8;
+-      karg.Configuration.usBIOSReleaseRevision =
+-          (ioc->biosVersion & 0x000000FF);
+-      karg.Configuration.uControllerFlags = CSMI_SAS_CNTLR_SAS_HBA |
+-          CSMI_SAS_CNTLR_FWD_SUPPORT | CSMI_SAS_CNTLR_FWD_ONLINE |
+-          CSMI_SAS_CNTLR_FWD_SRESET ;
+-
+-      /*
+-       * Enabling CSMI_SAS_CNTLR_SAS_RAID bit when IR fw detected
+-       */
+-      if (ioc->ir_firmware)
+-              karg.Configuration.uControllerFlags |= CSMI_SAS_CNTLR_SAS_RAID;
+-
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-      /* All Rrom entries will be zero. Skip them. */
+-      /* bReserved will also be zeros. */
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-              sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-              "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get Controller Status command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_cntlr_status(unsigned long arg)
+-{
+-
+-      CSMI_SAS_CNTLR_STATUS_BUFFER  __user *uarg = (void __user *) arg;
+-      MPT_ADAPTER             *ioc = NULL;
+-      CSMI_SAS_CNTLR_STATUS_BUFFER    karg;
+-      int                     iocnum;
+-      int                     rc;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-           "Unable to read in csmi_sas_get_cntlr_status_buffer struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      /* Fill in the data and return the structure to the calling
+-       * program
+-       */
+-
+-      rc = mpt_GetIocState(ioc, 1);
+-      switch (rc) {
+-      case MPI_IOC_STATE_OPERATIONAL:
+-              karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_GOOD;
+-              karg.Status.uOfflineReason = 0;
+-              break;
+-
+-      case MPI_IOC_STATE_FAULT:
+-              karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_FAILED;
+-              karg.Status.uOfflineReason = 0;
+-              break;
+-
+-      case MPI_IOC_STATE_RESET:
+-      case MPI_IOC_STATE_READY:
+-      default:
+-              karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_OFFLINE;
+-              karg.Status.uOfflineReason =
+-                  CSMI_SAS_OFFLINE_REASON_INITIALIZING;
+-              break;
+-      }
+-
+-      memset(&karg.Status.bReserved, 0, 28);
+-
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-              sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-                  "Unable to write out csmi_sas_get_cntlr_status @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get Phy Info command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_phy_info(unsigned long arg)
+-{
+-      CSMI_SAS_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_PHY_INFO_BUFFER  karg;
+-      MPT_ADAPTER             *ioc = NULL;
+-      ConfigExtendedPageHeader_t  hdr;
+-      CONFIGPARMS             cfg;
+-      SasIOUnitPage0_t        *sasIoUnitPg0;
+-      dma_addr_t              sasIoUnitPg0_dma;
+-      int                     sasIoUnitPg0_data_sz;
+-      SasPhyPage0_t           *sasPhyPg0;
+-      dma_addr_t              sasPhyPg0_dma;
+-      int                     sasPhyPg0_data_sz;
+-      u16                     protocol;
+-      int                     iocnum;
+-      int                     rc;
+-      int                     ii;
+-      u64                     sas_address;
+-      struct mptsas_devinfo   device_info;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-      sasIoUnitPg0=NULL;
+-      sasPhyPg0=NULL;
+-      sasIoUnitPg0_data_sz=0;
+-      sasPhyPg0_data_sz=0;
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-              "Unable to read in csmisas_get_phy_info_buffer struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      /* Fill in the data and return the structure to the calling
+-       * program
+-       */
+-      memset(&karg.Information, 0, sizeof(CSMI_SAS_PHY_INFO));
+-
+-      /* Issue a config request to get the number of phys
+-       */
+-      hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 0;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = 0;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              /* Don't check if this failed.  Already in a
+-               * failure case.
+-               */
+-              dcsmisasprintk((
+-                  ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: HEADER\n"));
+-              dcsmisasprintk((": rc=%x\n",rc));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto sas_get_phy_info_exit;
+-      }
+-
+-      if (hdr.ExtPageLength == 0) {
+-              /* Don't check if this failed.  Already in a
+-               * failure case.
+-               */
+-              dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto sas_get_phy_info_exit;
+-      }
+-
+-      sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
+-      rc = -ENOMEM;
+-
+-      sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
+-          sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
+-
+-      if (!sasIoUnitPg0) {
+-              dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto sas_get_phy_info_exit;
+-      }
+-
+-      memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
+-      cfg.physAddr = sasIoUnitPg0_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-
+-              /* Don't check if this failed.  Already in a
+-               * failure case.
+-               */
+-              dcsmisasprintk((
+-                  ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: PAGE\n"));
+-              dcsmisasprintk((": rc=%x\n",rc));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto sas_get_phy_info_exit;
+-      }
+-
+-      /* Number of Phys. */
+-      karg.Information.bNumberOfPhys = sasIoUnitPg0->NumPhys;
+-
+-      /* Fill in information for each phy. */
+-      for (ii = 0; ii < karg.Information.bNumberOfPhys; ii++) {
+-
+-/* EDM : dump IO Unit Page 0 data*/
+-              dcsmisasprintk(("---- IO UNIT PAGE 0 ------------\n"));
+-              dcsmisasprintk(("Handle=0x%X\n",
+-                  le16_to_cpu(sasIoUnitPg0->PhyData[ii].AttachedDeviceHandle)));
+-              dcsmisasprintk(("Controller Handle=0x%X\n",
+-                  le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle)));
+-              dcsmisasprintk(("Port=0x%X\n",
+-                  sasIoUnitPg0->PhyData[ii].Port));
+-              dcsmisasprintk(("Port Flags=0x%X\n",
+-                  sasIoUnitPg0->PhyData[ii].PortFlags));
+-              dcsmisasprintk(("PHY Flags=0x%X\n",
+-                  sasIoUnitPg0->PhyData[ii].PhyFlags));
+-              dcsmisasprintk(("Negotiated Link Rate=0x%X\n",
+-                  sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate));
+-              dcsmisasprintk(("Controller PHY Device Info=0x%X\n",
+-                  le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)));
+-              dcsmisasprintk(("DiscoveryStatus=0x%X\n",
+-                  le32_to_cpu(sasIoUnitPg0->PhyData[ii].DiscoveryStatus)));
+-              dcsmisasprintk(("\n"));
+-/* EDM : debug data */
+-
+-              /* PHY stuff. */
+-              karg.Information.Phy[ii].bPortIdentifier =
+-                  sasIoUnitPg0->PhyData[ii].Port;
+-
+-              /* Get the negotiated link rate for the phy. */
+-              switch (sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate) {
+-
+-              case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
+-                      karg.Information.Phy[ii].bNegotiatedLinkRate =
+-                          CSMI_SAS_PHY_DISABLED;
+-                      break;
+-
+-              case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
+-                      karg.Information.Phy[ii].bNegotiatedLinkRate =
+-                          CSMI_SAS_LINK_RATE_FAILED;
+-                      break;
+-
+-              case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
+-                      break;
+-
+-              case MPI_SAS_IOUNIT0_RATE_1_5:
+-                      karg.Information.Phy[ii].bNegotiatedLinkRate =
+-                          CSMI_SAS_LINK_RATE_1_5_GBPS;
+-                      break;
+-
+-              case MPI_SAS_IOUNIT0_RATE_3_0:
+-                      karg.Information.Phy[ii].bNegotiatedLinkRate =
+-                          CSMI_SAS_LINK_RATE_3_0_GBPS;
+-                      break;
+-
+-              case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
+-              default:
+-                      karg.Information.Phy[ii].bNegotiatedLinkRate =
+-                          CSMI_SAS_LINK_RATE_UNKNOWN;
+-                      break;
+-              }
+-
+-              if (sasIoUnitPg0->PhyData[ii].PortFlags &
+-                  MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS) {
+-                      karg.Information.Phy[ii].bAutoDiscover =
+-                          CSMI_SAS_DISCOVER_IN_PROGRESS;
+-              } else {
+-                      karg.Information.Phy[ii].bAutoDiscover =
+-                          CSMI_SAS_DISCOVER_COMPLETE;
+-              }
+-
+-              /* Issue a config request to get
+-               * phy information.
+-               */
+-              hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
+-              hdr.ExtPageLength = 0;
+-              hdr.PageNumber = 0;
+-              hdr.Reserved1 = 0;
+-              hdr.Reserved2 = 0;
+-              hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-              hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
+-
+-              cfg.cfghdr.ehdr = &hdr;
+-              cfg.physAddr = -1;
+-              cfg.pageAddr = ii;
+-              cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-              cfg.dir = 0;    /* read */
+-              cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-              if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-                      dcsmisasprintk((
+-                          ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
+-                      dcsmisasprintk((": rc=%x\n",rc));
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto sas_get_phy_info_exit;
+-              }
+-
+-              if (hdr.ExtPageLength == 0) {
+-                      dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto sas_get_phy_info_exit;
+-              }
+-
+-              sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
+-              rc = -ENOMEM;
+-
+-              sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(
+-                  ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma);
+-
+-              if (! sasPhyPg0) {
+-                      dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto sas_get_phy_info_exit;
+-              }
+-
+-              memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
+-              cfg.physAddr = sasPhyPg0_dma;
+-              cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-              if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-                      dcsmisasprintk((
+-                          ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
+-                      dcsmisasprintk((": rc=%x\n",rc));
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
+-                          (u8 *) sasPhyPg0, sasPhyPg0_dma);
+-                      goto sas_get_phy_info_exit;
+-              }
+-
+-/* EDM : dump PHY Page 0 data*/
+-              memcpy(&sas_address, &sasPhyPg0->SASAddress, sizeof(u64));
+-              dcsmisasprintk(("---- SAS PHY PAGE 0 ------------\n"));
+-              dcsmisasprintk(("Handle=0x%X\n",
+-                  le16_to_cpu(sasPhyPg0->AttachedDevHandle)));
+-              dcsmisasprintk(("SAS Address=0x%llX\n",
+-                  (unsigned long long)sas_address));
+-              dcsmisasprintk(("Attached PHY Identifier=0x%X\n",
+-                  sasPhyPg0->AttachedPhyIdentifier));
+-              dcsmisasprintk(("Attached Device Info=0x%X\n",
+-                  le32_to_cpu(sasPhyPg0->AttachedDeviceInfo)));
+-              dcsmisasprintk(("Programmed Link Rate=0x%X\n",
+-                  sasPhyPg0->ProgrammedLinkRate));
+-              dcsmisasprintk(("Hardware Link Rate=0x%X\n",
+-                  sasPhyPg0->HwLinkRate));
+-              dcsmisasprintk(("Change Count=0x%X\n",
+-                  sasPhyPg0->ChangeCount));
+-              dcsmisasprintk(("PHY Info=0x%X\n",
+-                  le32_to_cpu(sasPhyPg0->PhyInfo)));
+-              dcsmisasprintk(("\n"));
+-/* EDM : debug data */
+-
+-              /* save the data */
+-
+-              /* Set Max hardware link rate.
+-               * This value is hard coded
+-               * because the HW link rate
+-               * is currently being
+-               * overwritten in FW.
+-               */
+-
+-              /* Set Max hardware link rate. */
+-              switch (sasPhyPg0->HwLinkRate &
+-                  MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
+-
+-              case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
+-                      karg.Information.Phy[ii].bMaximumLinkRate =
+-                          CSMI_SAS_LINK_RATE_1_5_GBPS;
+-                      break;
+-
+-              case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
+-                      karg.Information.Phy[ii].bMaximumLinkRate =
+-                          CSMI_SAS_LINK_RATE_3_0_GBPS;
+-                      break;
+-              default:
+-                      break;
+-              }
+-
+-              /* Set Max programmed link rate. */
+-              switch (sasPhyPg0->ProgrammedLinkRate &
+-                  MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
+-
+-              case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
+-                      karg.Information.Phy[ii].bMaximumLinkRate |=
+-                          (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
+-                      break;
+-
+-              case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
+-                      karg.Information.Phy[ii].bMaximumLinkRate |=
+-                          (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
+-                      break;
+-              default:
+-                      break;
+-              }
+-
+-              /* Set Min hardware link rate. */
+-              switch (sasPhyPg0->HwLinkRate &
+-                  MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
+-
+-              case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
+-                      karg.Information.Phy[ii].bMinimumLinkRate =
+-                          CSMI_SAS_LINK_RATE_1_5_GBPS;
+-                      break;
+-
+-              case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
+-                      karg.Information.Phy[ii].bMinimumLinkRate =
+-                          CSMI_SAS_LINK_RATE_3_0_GBPS;
+-                      break;
+-              default:
+-                      break;
+-              }
+-
+-              /* Set Min programmed link rate. */
+-              switch (sasPhyPg0->ProgrammedLinkRate &
+-                  MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
+-
+-              case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
+-                      karg.Information.Phy[ii].bMinimumLinkRate |=
+-                          (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
+-                      break;
+-
+-              case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
+-                      karg.Information.Phy[ii].bMinimumLinkRate |=
+-                          (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
+-                      break;
+-              default:
+-                      break;
+-              }
+-
+-              karg.Information.Phy[ii].bPhyChangeCount = sasPhyPg0->ChangeCount;
+-              if( sasPhyPg0->PhyInfo & MPI_SAS_PHY0_PHYINFO_VIRTUAL_PHY )
+-                      karg.Information.Phy[ii].bPhyFeatures = CSMI_SAS_PHY_VIRTUAL_SMP;
+-
+-              /* Fill in Attached Device
+-               * Initiator Port Protocol.
+-               * Bits 6:3
+-               * More than one bit can be set.
+-               */
+-              protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x78;
+-              karg.Information.Phy[ii].Attached.bInitiatorPortProtocol = 0;
+-              if (protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
+-                    karg.Information.Phy[ii].Attached.bInitiatorPortProtocol =
+-                          CSMI_SAS_PROTOCOL_SSP;
+-              if (protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
+-                   karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_STP;
+-              if (protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
+-                   karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SMP;
+-              if (protocol & MPI_SAS_DEVICE_INFO_SATA_HOST)
+-                   karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SATA;
+-
+-              /* Fill in Phy Target Port
+-               * Protocol. Bits 10:7
+-               * More than one bit can be set.
+-               */
+-              protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x780;
+-              karg.Information.Phy[ii].Attached.bTargetPortProtocol = 0;
+-              if (protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+-                      karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SSP;
+-              if (protocol & MPI_SAS_DEVICE_INFO_STP_TARGET)
+-                      karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_STP;
+-              if (protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET)
+-                      karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SMP;
+-              if (protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+-                      karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SATA;
+-
+-
+-              /* Fill in Attached device type */
+-              switch (le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
+-                  MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
+-
+-              case MPI_SAS_DEVICE_INFO_NO_DEVICE:
+-                      karg.Information.Phy[ii].Attached.bDeviceType =
+-                          CSMI_SAS_NO_DEVICE_ATTACHED;
+-                      break;
+-
+-              case MPI_SAS_DEVICE_INFO_END_DEVICE:
+-                      karg.Information.Phy[ii].Attached.bDeviceType =
+-                          CSMI_SAS_END_DEVICE;
+-                      break;
+-
+-              case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
+-                      karg.Information.Phy[ii].Attached.bDeviceType =
+-                          CSMI_SAS_EDGE_EXPANDER_DEVICE;
+-                      break;
+-
+-              case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
+-                      karg.Information.Phy[ii].Attached.bDeviceType =
+-                          CSMI_SAS_FANOUT_EXPANDER_DEVICE;
+-                      break;
+-              }
+-
+-              /* Identify Info. */
+-              switch (le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) &
+-                  MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
+-
+-              case MPI_SAS_DEVICE_INFO_NO_DEVICE:
+-                      karg.Information.Phy[ii].Identify.bDeviceType =
+-                          CSMI_SAS_NO_DEVICE_ATTACHED;
+-                      break;
+-
+-              case MPI_SAS_DEVICE_INFO_END_DEVICE:
+-                      karg.Information.Phy[ii].Identify.bDeviceType =
+-                          CSMI_SAS_END_DEVICE;
+-                      break;
+-
+-              case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
+-                      karg.Information.Phy[ii].Identify.bDeviceType =
+-                          CSMI_SAS_EDGE_EXPANDER_DEVICE;
+-                      break;
+-
+-              case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
+-                      karg.Information.Phy[ii].Identify.bDeviceType =
+-                          CSMI_SAS_FANOUT_EXPANDER_DEVICE;
+-                      break;
+-              }
+-
+-              /* Fill in Phy Initiator Port Protocol. Bits 6:3
+-               * More than one bit can be set, fall through cases.
+-               */
+-              protocol = le32_to_cpu(
+-                  sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x78;
+-              karg.Information.Phy[ii].Identify.bInitiatorPortProtocol = 0;
+-              if( protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR )
+-                   karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SSP;
+-              if( protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR )
+-                   karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_STP;
+-              if( protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR )
+-                   karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SMP;
+-              if( protocol & MPI_SAS_DEVICE_INFO_SATA_HOST )
+-                   karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SATA;
+-
+-              /* Fill in Phy Target Port Protocol. Bits 10:7
+-               * More than one bit can be set, fall through cases.
+-               */
+-              protocol = le32_to_cpu(
+-                  sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x780;
+-              karg.Information.Phy[ii].Identify.bTargetPortProtocol = 0;
+-              if( protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET )
+-                      karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SSP;
+-              if( protocol & MPI_SAS_DEVICE_INFO_STP_TARGET )
+-                      karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_STP;
+-              if( protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET )
+-                      karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SMP;
+-              if( protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE )
+-                      karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
+-                          CSMI_SAS_PROTOCOL_SATA;
+-
+-              /* Setup SAS Address for the attached device */
+-              if (sasPhyPg0->AttachedDevHandle) {
+-                      sas_address = reverse_byte_order64(sas_address);
+-                      memcpy(karg.Information.Phy[ii].Attached.bSASAddress,
+-                          &sas_address, sizeof(u64));
+-                      karg.Information.Phy[ii].Attached.bPhyIdentifier =
+-                          sasPhyPg0->AttachedPhyIdentifier;
+-              }
+-
+-              /* Setup SAS Address for the parent device */
+-              csmisas_sas_device_pg0(ioc, &device_info,
+-                  (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+-                  MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+-                  sasIoUnitPg0->PhyData[ii].ControllerDevHandle);
+-              sas_address = reverse_byte_order64(device_info.sas_address);
+-              memcpy(karg.Information.Phy[ii].Identify.bSASAddress,
+-                  &sas_address, sizeof(u64));
+-              karg.Information.Phy[ii].Identify.bPhyIdentifier = ii;
+-
+-              pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
+-                  (u8 *) sasPhyPg0, sasPhyPg0_dma);
+-      }
+-
+-sas_get_phy_info_exit:
+-
+-      if (sasIoUnitPg0)
+-              pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
+-                  (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-          sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-                  "Unable to write out csmisas_get_phy_info_buffer @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Set PHY Info command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_set_phy_info(unsigned long arg)
+-{
+-      CSMI_SAS_SET_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_SET_PHY_INFO_BUFFER     karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      int                             iocnum;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_set_phy_info struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-/* TODO - implement IOCTL here */
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
+-      dcsmisasprintk((": not implemented\n"));
+-
+-// cim_set_phy_info_exit:
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-                              sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to write out csmi_sas_set_phy_info @ %p\n",
+-                              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get SCSI Address command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_scsi_address(unsigned long arg)
+-{
+-      CSMI_SAS_GET_SCSI_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_GET_SCSI_ADDRESS_BUFFER         karg;
+-      MPT_ADAPTER             *ioc = NULL;
+-      int                     iocnum;
+-      u64                     sas_address;
+-      struct sas_device_info  *sas_info;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg,
+-          sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_get_scsi_address struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-            "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      /* reverse byte order the sas address */
+-      memcpy(&sas_address, karg.bSASAddress, sizeof(u64));
+-      sas_address = reverse_byte_order64(sas_address);
+-
+-      /* Search the list for the matching SAS address. */
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SCSI_ADDRESS;
+-      karg.bPathId = 0;
+-      karg.bTargetId = 0;
+-      karg.bLun = 0;
+-
+-      sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
+-      if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
+-              goto csmisas_get_scsi_address_exit;
+-
+-      karg.bPathId = sas_info->os.channel;
+-      karg.bTargetId = sas_info->os.id;
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+- csmisas_get_scsi_address_exit:
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-          sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to write out csmi_sas_get_scsi_address @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get SCSI Address command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_sata_signature(unsigned long arg)
+-{
+-      CSMI_SAS_SATA_SIGNATURE_BUFFER  __user *uarg = (void __user *) arg;
+-      CSMI_SAS_SATA_SIGNATURE_BUFFER   karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      int                             iocnum;
+-      int                             rc, jj;
+-      ConfigExtendedPageHeader_t      hdr;
+-      CONFIGPARMS                     cfg;
+-      SasPhyPage0_t                   *sasPhyPg0;
+-      dma_addr_t                      sasPhyPg0_dma;
+-      int                             sasPhyPg0_data_sz;
+-      SasDevicePage1_t                *sasDevicePg1;
+-      dma_addr_t                      sasDevicePg1_dma;
+-      int                             sasDevicePg1_data_sz;
+-      u8                              phyId;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-      sasPhyPg0=NULL;
+-      sasPhyPg0_data_sz=0;
+-      sasDevicePg1=NULL;
+-      sasDevicePg1_data_sz=0;
+-
+-      if (copy_from_user(&karg, uarg,
+-           sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_sata_signature struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-          "%s::%s() @%d - ioc%d not found!\n",
+-                   __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      phyId = karg.Signature.bPhyIdentifier;
+-      if (phyId >= ioc->num_ports) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
+-              dcsmisasprintk((": phyId >= ioc->num_ports\n"));
+-              goto cim_sata_signature_exit;
+-      }
+-
+-      /* Default to success.*/
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-      /* Issue a config request to get the devHandle of the attached device
+-       */
+-
+-      /* Issue a config request to get phy information. */
+-      hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 0;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = phyId;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              /* Don't check if this failed.  Already in a
+-               * failure case.
+-               */
+-              dcsmisasprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
+-              dcsmisasprintk((": rc=%x\n",rc));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sata_signature_exit;
+-      }
+-
+-      if (hdr.ExtPageLength == 0) {
+-              /* Don't check if this failed.  Already in a
+-               * failure case.
+-               */
+-              dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sata_signature_exit;
+-      }
+-
+-
+-      sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
+-      rc = -ENOMEM;
+-
+-      sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(ioc->pcidev,
+-          sasPhyPg0_data_sz, &sasPhyPg0_dma);
+-
+-      if (! sasPhyPg0) {
+-              dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sata_signature_exit;
+-      }
+-
+-      memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
+-      cfg.physAddr = sasPhyPg0_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              /* Don't check if this failed.  Already in a
+-               * failure case.
+-               */
+-              dcsmisasprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
+-              dcsmisasprintk((": rc=%x\n",rc));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sata_signature_exit;
+-      }
+-
+-      /* Make sure a SATA device is attached. */
+-      if ((le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
+-          MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0) {
+-              dcsmisasprintk((": NOT A SATA DEVICE\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SATA_DEVICE;
+-              goto cim_sata_signature_exit;
+-      }
+-
+-      /* Get device page 1 for FIS  signature. */
+-      hdr.PageVersion = MPI_SASDEVICE1_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 1 /* page number 1 */;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.physAddr = -1;
+-
+-      cfg.pageAddr = ((MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+-          MPI_SAS_DEVICE_PGAD_FORM_SHIFT) |
+-          le16_to_cpu(sasPhyPg0->AttachedDevHandle));
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              dcsmisasprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: HEADER\n"));
+-              dcsmisasprintk((": rc=%x\n",rc));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sata_signature_exit;
+-      }
+-
+-      if (hdr.ExtPageLength == 0) {
+-              dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sata_signature_exit;
+-      }
+-
+-      sasDevicePg1_data_sz = hdr.ExtPageLength * 4;
+-      rc = -ENOMEM;
+-
+-      sasDevicePg1 = (SasDevicePage1_t *) pci_alloc_consistent
+-          (ioc->pcidev, sasDevicePg1_data_sz, &sasDevicePg1_dma);
+-
+-      if (! sasDevicePg1) {
+-              dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sata_signature_exit;
+-      }
+-
+-      memset((u8 *)sasDevicePg1, 0, sasDevicePg1_data_sz);
+-      cfg.physAddr = sasDevicePg1_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              dcsmisasprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: PAGE\n"));
+-              dcsmisasprintk((": rc=%x\n",rc));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sata_signature_exit;
+-      }
+-
+-/* EDM : dump Device Page 1 data*/
+-      dcsmisasprintk(("---- SAS DEVICE PAGE 1 ---------\n"));
+-      dcsmisasprintk(("Handle=0x%x\n",sasDevicePg1->DevHandle));
+-      dcsmisasprintk(("SAS Address="));
+-      for(jj=0;jj<8;jj++)
+-              dcsmisasprintk(("%02x ",
+-              ((u8 *)&sasDevicePg1->SASAddress)[jj]));
+-      dcsmisasprintk(("\n"));
+-      dcsmisasprintk(("Target ID=0x%x\n",sasDevicePg1->TargetID));
+-      dcsmisasprintk(("Bus=0x%x\n",sasDevicePg1->Bus));
+-      dcsmisasprintk(("Initial Reg Device FIS="));
+-      for(jj=0;jj<20;jj++)
+-              dcsmisasprintk(("%02x ",
+-              ((u8 *)&sasDevicePg1->InitialRegDeviceFIS)[jj]));
+-      dcsmisasprintk(("\n\n"));
+-/* EDM : debug data */
+-
+-      memcpy(karg.Signature.bSignatureFIS,
+-              sasDevicePg1->InitialRegDeviceFIS,20);
+-
+- cim_sata_signature_exit:
+-
+-      if (sasPhyPg0)
+-              pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
+-                  (u8 *) sasPhyPg0, sasPhyPg0_dma);
+-
+-      if (sasDevicePg1)
+-              pci_free_consistent(ioc->pcidev, sasDevicePg1_data_sz,
+-                  (u8 *) sasDevicePg1, sasDevicePg1_dma);
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-          sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to write out csmi_sas_sata_signature @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get SCSI Address command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_device_address(unsigned long arg)
+-{
+-      CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER       karg;
+-      MPT_ADAPTER             *ioc = NULL;
+-      int                     iocnum;
+-      struct sas_device_info  *sas_info;
+-      u64                     sas_address;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg,
+-          sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-         "Unable to read in csmi_sas_get_device_address_buffer struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-          "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_DEVICE_ADDRESS;
+-      memset(karg.bSASAddress, 0, sizeof(u64));
+-      memset(karg.bSASLun, 0, sizeof(karg.bSASLun));
+-
+-      /* Search the list for the matching SAS address. */
+-      sas_info = csmisas_get_device_component_by_os(ioc, karg.bPathId,
+-          karg.bTargetId);
+-      if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
+-              goto csmisas_get_device_address_exit;
+-
+-      sas_address = reverse_byte_order64(sas_info->sas_address);
+-      memcpy(karg.bSASAddress, &sas_address, sizeof(u64));
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+- csmisas_get_device_address_exit:
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-          sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-              "Unable to write out csmi_sas_get_device_address_buffer @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI Sas Get Link Errors command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_link_errors(unsigned long arg)
+-{
+-      CSMI_SAS_LINK_ERRORS_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_LINK_ERRORS_BUFFER      karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      MPT_FRAME_HDR                   *mf = NULL;
+-      MPIHeader_t                     *mpi_hdr;
+-      int                             iocnum;
+-      int                             rc;
+-      ConfigExtendedPageHeader_t      hdr;
+-      CONFIGPARMS                     cfg;
+-      SasPhyPage1_t                   *sasPhyPage1;
+-      dma_addr_t                      sasPhyPage1_dma;
+-      int                             sasPhyPage1_data_sz;
+-      SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
+-      SasIoUnitControlReply_t         *sasIoUnitCntrReply;
+-      u8                              phyId;
+-      u16                             ioc_status;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-      sasPhyPage1=NULL;
+-      sasPhyPage1_data_sz=0;
+-
+-      if (copy_from_user(&karg, uarg,
+-           sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmisas_get_link_errors struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-          "%s::%s() @%d - ioc%d not found!\n",
+-                   __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      phyId = karg.Information.bPhyIdentifier;
+-      if (phyId >= ioc->num_ports) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
+-              dcsmisasprintk((": phyId >= ioc->num_ports\n"));
+-              goto cim_get_link_errors_exit;
+-      }
+-
+-      /* Default to success.*/
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-      /* Issue a config request to get the devHandle of the attached device
+-       */
+-
+-      /* Issue a config request to get phy information. */
+-      hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 1 /* page number 1*/;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = phyId;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              /* Don't check if this failed.  Already in a
+-               * failure case.
+-               */
+-              dcsmisasprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: HEADER\n"));
+-              dcsmisasprintk((": rc=%x\n",rc));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_link_errors_exit;
+-      }
+-
+-      if (hdr.ExtPageLength == 0) {
+-              /* Don't check if this failed.  Already in a
+-               * failure case.
+-               */
+-              dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_link_errors_exit;
+-      }
+-
+-
+-      sasPhyPage1_data_sz = hdr.ExtPageLength * 4;
+-      rc = -ENOMEM;
+-
+-      sasPhyPage1 = (SasPhyPage1_t *) pci_alloc_consistent(ioc->pcidev,
+-          sasPhyPage1_data_sz, &sasPhyPage1_dma);
+-
+-      if (! sasPhyPage1) {
+-              dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_link_errors_exit;
+-      }
+-
+-      memset((u8 *)sasPhyPage1, 0, sasPhyPage1_data_sz);
+-      cfg.physAddr = sasPhyPage1_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              /* Don't check if this failed.  Already in a
+-               * failure case.
+-               */
+-              dcsmisasprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: PAGE\n"));
+-              dcsmisasprintk((": rc=%x\n",rc));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_link_errors_exit;
+-      }
+-
+-/* EDM : dump PHY Page 1 data*/
+-      dcsmisasprintk(("---- SAS PHY PAGE 1 ------------\n"));
+-      dcsmisasprintk(("Invalid Dword Count=0x%x\n",
+-          sasPhyPage1->InvalidDwordCount));
+-      dcsmisasprintk(("Running Disparity Error Count=0x%x\n",
+-          sasPhyPage1->RunningDisparityErrorCount));
+-      dcsmisasprintk(("Loss Dword Synch Count=0x%x\n",
+-          sasPhyPage1->LossDwordSynchCount));
+-      dcsmisasprintk(("PHY Reset Problem Count=0x%x\n",
+-          sasPhyPage1->PhyResetProblemCount));
+-      dcsmisasprintk(("\n\n"));
+-/* EDM : debug data */
+-
+-      karg.Information.uInvalidDwordCount =
+-              le32_to_cpu(sasPhyPage1->InvalidDwordCount);
+-      karg.Information.uRunningDisparityErrorCount =
+-              le32_to_cpu(sasPhyPage1->RunningDisparityErrorCount);
+-      karg.Information.uLossOfDwordSyncCount =
+-              le32_to_cpu(sasPhyPage1->LossDwordSynchCount);
+-      karg.Information.uPhyResetProblemCount =
+-              le32_to_cpu(sasPhyPage1->PhyResetProblemCount);
+-
+-      if (karg.Information.bResetCounts ==
+-          CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS ) {
+-              goto cim_get_link_errors_exit;
+-      }
+-
+-      /* Clear Error log
+-       *
+-       * Issue IOUNIT Control Reqeust Message
+-       */
+-
+-      /* Get a MF for this command.
+-       */
+-      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-              dcsmisasprintk((": no msg frames!\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_link_errors_exit;
+-        }
+-
+-      mpi_hdr = (MPIHeader_t *) mf;
+-      sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+-      memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
+-      sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
+-      sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
+-      sasIoUnitCntrReq->PhyNum = phyId;
+-      sasIoUnitCntrReq->Operation = MPI_SAS_OP_PHY_CLEAR_ERROR_LOG;
+-
+-      if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_link_errors_exit;
+-      }
+-
+-      /* process the completed Reply Message Frame */
+-      if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+-
+-              sasIoUnitCntrReply =
+-                  (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame;
+-              ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus)
+-                  & MPI_IOCSTATUS_MASK;
+-
+-              if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
+-                      dcsmisasprintk((": SAS IO Unit Control: "));
+-                      dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n",
+-                          sasIoUnitCntrReply->IOCStatus,
+-                          sasIoUnitCntrReply->IOCLogInfo));
+-              }
+-      }
+-
+- cim_get_link_errors_exit:
+-
+-      if (sasPhyPage1)
+-              pci_free_consistent(ioc->pcidev, sasPhyPage1_data_sz,
+-                  (u8 *) sasPhyPage1, sasPhyPage1_dma);
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-          sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to write out csmisas_get_link_errors @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS SMP Passthru command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_smp_passthru(unsigned long arg)
+-{
+-      CSMI_SAS_SMP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
+-      MPT_ADAPTER                     *ioc;
+-      CSMI_SAS_SMP_PASSTHRU_BUFFER     karg;
+-      pSmpPassthroughRequest_t        smpReq;
+-      pSmpPassthroughReply_t          smpReply;
+-      MPT_FRAME_HDR                   *mf = NULL;
+-      MPIHeader_t                     *mpi_hdr;
+-      char                            *psge;
+-      int                             iocnum, flagsLength;
+-      void *                          request_data;
+-      dma_addr_t                      request_data_dma;
+-      u32                             request_data_sz;
+-      void *                          response_data;
+-      dma_addr_t                      response_data_dma;
+-      u32                             response_data_sz;
+-      u16                             ioc_status;
+-      u64                             sas_address;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_smp_passthru struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      request_data = NULL;
+-      response_data = NULL;
+-      response_data_sz = sizeof(CSMI_SAS_SMP_RESPONSE);
+-      request_data_sz  = karg.Parameters.uRequestLength;
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      /* Make sure the adapter is not being reset. */
+-      if (!ioc->ioctl) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-                  "No memory available during driver init.\n",
+-                  __FILE__, __LINE__,__FUNCTION__);
+-              return -ENOMEM;
+-      } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
+-              printk(KERN_ERR "%s@%d::%s - "
+-                  "Busy with IOC Reset \n",
+-                  __FILE__, __LINE__,__FUNCTION__);
+-              return -EBUSY;
+-      }
+-
+-      /* Default to success.*/
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-      /* Do some error checking on the request. */
+-      if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
+-              goto cim_smp_passthru_exit;
+-      }
+-
+-      if ((request_data_sz > 0xFFFF) || (!request_data_sz)) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_smp_passthru_exit;
+-      }
+-
+-      /* Get a free request frame and save the message context.
+-       */
+-      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-              dcsmisasprintk((": no msg frames!\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_smp_passthru_exit;
+-        }
+-
+-      mpi_hdr = (MPIHeader_t *) mf;
+-      smpReq = (pSmpPassthroughRequest_t ) mf;
+-
+-      memset(smpReq,0,ioc->req_sz);
+-
+-      memcpy(&sas_address, karg.Parameters.bDestinationSASAddress,
+-          sizeof(u64));
+-      sas_address = cpu_to_le64(reverse_byte_order64(sas_address));
+-      memcpy(&smpReq->SASAddress, &sas_address, sizeof(u64));
+-
+-      /* Fill in smp request. */
+-      smpReq->PhysicalPort = karg.Parameters.bPortIdentifier;
+-      smpReq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
+-      smpReq->RequestDataLength = cpu_to_le16(request_data_sz);
+-      smpReq->ConnectionRate = karg.Parameters.bConnectionRate;
+-      smpReq->MsgContext = mpi_hdr->MsgContext;
+-      smpReq->Reserved2 = 0;
+-      smpReq->Reserved3 = 0;
+-
+-      /*
+-       * Prepare the necessary pointers to run
+-       * through the SGL generation
+-       */
+-
+-      psge = (char *)&smpReq->SGL;
+-
+-      /* setup the *Request* payload SGE */
+-      flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+-              MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+-              MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+-              MPI_SGE_FLAGS_HOST_TO_IOC |
+-              MPI_SGE_FLAGS_END_OF_BUFFER;
+-
+-      if (sizeof(dma_addr_t) == sizeof(u64)) {
+-              flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
+-      }
+-      flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
+-      flagsLength |= request_data_sz;
+-
+-      request_data = pci_alloc_consistent(
+-          ioc->pcidev, request_data_sz, &request_data_dma);
+-
+-      if (!request_data) {
+-              dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              mpt_free_msg_frame(ioc, mf);
+-              goto cim_smp_passthru_exit;
+-      }
+-
+-      mpt_add_sge(psge, flagsLength, request_data_dma);
+-      psge += (sizeof(u32) + sizeof(dma_addr_t));
+-
+-      memcpy(request_data,&karg.Parameters.Request,request_data_sz);
+-
+-      /* setup the *Response* payload SGE */
+-      response_data = pci_alloc_consistent(
+-          ioc->pcidev, response_data_sz, &response_data_dma);
+-
+-      if (!response_data) {
+-              dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              mpt_free_msg_frame(ioc, mf);
+-              goto cim_smp_passthru_exit;
+-      }
+-
+-      flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+-              MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+-              MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+-              MPI_SGE_FLAGS_IOC_TO_HOST |
+-              MPI_SGE_FLAGS_END_OF_BUFFER;
+-
+-      if (sizeof(dma_addr_t) == sizeof(u64)) {
+-              flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
+-      }
+-
+-      flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
+-      flagsLength |= response_data_sz;
+-
+-      mpt_add_sge(psge, flagsLength, response_data_dma);
+-
+-      if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_smp_passthru_exit;
+-      }
+-
+-      if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) {
+-              dcsmisasprintk((": SMP Passthru: oh no, there is no reply!!"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_smp_passthru_exit;
+-      }
+-
+-      /* process the completed Reply Message Frame */
+-      smpReply = (pSmpPassthroughReply_t )ioc->ioctl->ReplyFrame;
+-      ioc_status = le16_to_cpu(smpReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+-
+-      if ((ioc_status != MPI_IOCSTATUS_SUCCESS) &&
+-          (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              dcsmisasprintk((": SMP Passthru: "));
+-              dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
+-                  le16_to_cpu(smpReply->IOCStatus),
+-                  le32_to_cpu(smpReply->IOCLogInfo),
+-                  smpReply->SASStatus));
+-              goto cim_smp_passthru_exit;
+-      }
+-
+-      karg.Parameters.bConnectionStatus =
+-          map_sas_status_to_csmi(smpReply->SASStatus);
+-
+-
+-      if (le16_to_cpu(smpReply->ResponseDataLength)) {
+-              karg.Parameters.uResponseBytes = le16_to_cpu(smpReply->ResponseDataLength);
+-              memcpy(&karg.Parameters.Response,
+-                  response_data, le16_to_cpu(smpReply->ResponseDataLength));
+-      }
+-
+- cim_smp_passthru_exit:
+-
+-      if (request_data)
+-              pci_free_consistent(ioc->pcidev, request_data_sz,
+-                  (u8 *)request_data, request_data_dma);
+-
+-      if (response_data)
+-              pci_free_consistent(ioc->pcidev, response_data_sz,
+-                  (u8 *)response_data, response_data_dma);
+-
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-                              sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to write out csmi_sas_smp_passthru @ %p\n",
+-                              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk((": %s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS SSP Passthru command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int csmisas_ssp_passthru(unsigned long arg)
+-{
+-      CSMI_SAS_SSP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_SSP_PASSTHRU_BUFFER     karg_hdr, * karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      pSCSIIORequest_t                pScsiRequest;
+-      pSCSIIOReply_t                  pScsiReply;
+-      MPT_FRAME_HDR                   *mf = NULL;
+-      MPIHeader_t                     *mpi_hdr;
+-      int                             iocnum,ii;
+-      u64                             sas_address;
+-      u16                             req_idx;
+-      char                            *psge;
+-      int                             flagsLength;
+-      void *                          request_data;
+-      dma_addr_t                      request_data_dma;
+-      u32                             request_data_sz;
+-      int                             malloc_data_sz;
+-      int                             memory_pages;
+-      u16                             ioc_status;
+-      u8                              volume_id;
+-      u8                              volume_bus;
+-      u8                              is_hidden_raid_component;
+-      u8                              channel;
+-      u8                              id;
+-      struct sas_device_info          *sas_info;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg_hdr, uarg, sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      request_data = NULL;
+-      request_data_sz = karg_hdr.Parameters.uDataLength;
+-      channel = 0;
+-      id = 0;
+-      volume_id = 0;
+-      volume_bus = 0;
+-      is_hidden_raid_component = 0;
+-
+-      malloc_data_sz = (request_data_sz +
+-          offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer));
+-      memory_pages = get_order(malloc_data_sz);
+-      karg = (CSMI_SAS_SSP_PASSTHRU_BUFFER *)__get_free_pages(
+-              GFP_KERNEL, memory_pages);
+-      if (!karg){
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to malloc SAS_SSP_PASSTHRU_BUFFER "
+-                      "malloc_data_sz=%d memory_pages=%d\n",
+-                      __FILE__, __LINE__, __FUNCTION__,
+-                      malloc_data_sz, memory_pages);
+-              return -ENOMEM;
+-      }
+-
+-      dcsmisasprintk((KERN_ERR "%s@%d::%s() - "
+-                      "malloc'ed SAS_SSP_PASSTHRU_BUFFER "
+-                      "malloc_data_sz=%d memory_pages=%d\n",
+-                      __FILE__, __LINE__, __FUNCTION__,
+-                      malloc_data_sz, memory_pages));
+-
+-      memset(karg, 0, sizeof(*karg));
+-
+-      if (copy_from_user(karg, uarg, request_data_sz +
+-          offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      /*
+-       * some checks of the incoming frame
+-       */
+-      if ( offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer) +
+-          request_data_sz - sizeof(IOCTL_HEADER) >
+-          karg->IoctlHeader.Length ) {
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s()"
+-                  " @%d - expected datalen incorrect!\n",
+-                  __FILE__, __FUNCTION__, __LINE__));
+-              goto cim_ssp_passthru_exit;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              goto cim_ssp_passthru_exit;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s()"
+-                  " @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              goto cim_ssp_passthru_exit;
+-      }
+-
+-      /* Default to success.
+-       */
+-      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-      /* Neither a phy nor a port has been selected.
+-       */
+-      if ((karg->Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
+-              (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s()"
+-                  " @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
+-                  __FILE__, __FUNCTION__, __LINE__));
+-              goto cim_ssp_passthru_exit;
+-      }
+-
+-      /* A phy has been selected. Verify that it's valid.
+-       */
+-      if (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
+-
+-              /* Is the phy in range? */
+-              if (karg->Parameters.bPhyIdentifier >= ioc->num_ports) {
+-                      dcsmisasprintk((": phyId >= ioc->num_ports (%d %d)\n",
+-                          karg->Parameters.bPhyIdentifier,
+-                          ioc->num_ports));
+-                      karg->IoctlHeader.ReturnCode =
+-                          CSMI_SAS_PHY_DOES_NOT_EXIST;
+-                      goto cim_ssp_passthru_exit;
+-              }
+-      }
+-
+-      if(karg->Parameters.bAdditionalCDBLength) {
+-      /* TODO - SCSI IO (32) Request Message support
+-       */
+-              dcsmisasprintk((": greater than 16-byte cdb is not supported!\n"));
+-              karg->IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              goto cim_ssp_passthru_exit;
+-      }
+-
+-      /* we will use SAS address to resolve the scsi adddressing
+-       */
+-      memcpy(&sas_address, karg->Parameters.bDestinationSASAddress,
+-          sizeof(u64));
+-      sas_address = reverse_byte_order64(sas_address);
+-
+-      /* Search the list for the matching SAS address.
+-       */
+-      sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
+-      if (!sas_info || sas_info->is_cached) {
+-              /*
+-               *Invalid SAS address
+-               */
+-              karg->IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s()"
+-                  " @%d - couldn't find associated SASAddress=%llX!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, sas_address));
+-              goto cim_ssp_passthru_exit;
+-      }
+-
+-      id = sas_info->fw.id;
+-      channel = sas_info->fw.channel;
+-
+-      if (csmisas_is_phys_disk(ioc, channel, id)) {
+-              id = csmisas_raid_id_to_num(ioc, channel, id);
+-              channel = 0;
+-              is_hidden_raid_component = 1;
+-      }
+-
+-      /* Get a free request frame and save the message context.
+-       */
+-      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-              dcsmisasprintk((": no msg frames!\n"));
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_ssp_passthru_exit;
+-        }
+-
+-      mpi_hdr = (MPIHeader_t *) mf;
+-      pScsiRequest = (pSCSIIORequest_t) mf;
+-      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-
+-      memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
+-
+-      /* Fill in SCSI IO (16) request.
+-       */
+-
+-      pScsiRequest->Function = (is_hidden_raid_component == 1) ?
+-          MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : MPI_FUNCTION_SCSI_IO_REQUEST;
+-      pScsiRequest->TargetID = id;
+-      pScsiRequest->Bus = channel;
+-      memcpy(pScsiRequest->LUN, &karg->Parameters.bLun, 8);
+-      pScsiRequest->CDBLength = karg->Parameters.bCDBLength;
+-      pScsiRequest->DataLength = cpu_to_le32(request_data_sz);
+-      pScsiRequest->MsgContext = mpi_hdr->MsgContext;
+-      memcpy(pScsiRequest->CDB, karg->Parameters.bCDB,
+-          pScsiRequest->CDBLength);
+-
+-      #if defined(MPT_DEBUG_CSMISAS)
+-      {
+-      int k;
+-              printk("\tchannel=%d id=%d ", sas_info->fw.channel,
+-                  sas_info->fw.id);
+-              if (is_hidden_raid_component)
+-                      printk("num_id=%d ", id);
+-              printk("\n");
+-              printk("\tcdb_len = %d data_len=%d\n",
+-                  pScsiRequest->CDBLength, request_data_sz);
+-              printk("\t");
+-              for (k = 0; k < pScsiRequest->CDBLength; ++k)
+-                      printk(" %02x", pScsiRequest->CDB[k]);
+-              printk("\n");
+-      }
+-      #endif
+-
+-      /* direction
+-       */
+-      if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) {
+-              pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
+-      } else if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
+-              pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_WRITE);
+-      } else if ((karg->Parameters.uFlags & CSMI_SAS_SSP_UNSPECIFIED) &&
+-          (!karg->Parameters.uDataLength)) {
+-              /* no data transfer
+-               */
+-              pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_NODATATRANSFER);
+-      } else {
+-              /* no direction specified
+-               */
+-              pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
+-              pScsiRequest->MsgFlags =
+-                  MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR;
+-      }
+-
+-      pScsiRequest->MsgFlags |= mpt_msg_flags();
+-      /* task attributes
+-       */
+-      if((karg->Parameters.uFlags && 0xFF) == 0) {
+-              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
+-      } else if (karg->Parameters.uFlags &
+-          CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE) {
+-              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_HEADOFQ);
+-      } else if (karg->Parameters.uFlags &
+-          CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED) {
+-              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ORDEREDQ);
+-      } else if (karg->Parameters.uFlags &
+-          CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA) {
+-              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ACAQ);
+-      } else {
+-              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_UNTAGGED);
+-      }
+-
+-      /* setup sense
+-       */
+-      pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
+-      pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
+-          (req_idx * MPT_SENSE_BUFFER_ALLOC));
+-
+-      /* setup databuffer sg, assuming we fit everything one contiguous buffer
+-       */
+-      psge = (char *)&pScsiRequest->SGL;
+-
+-      if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
+-              flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
+-      } else if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) {
+-              flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
+-      }else {
+-              flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+-                              MPI_SGE_FLAGS_DIRECTION |
+-                              mpt_addr_size() )
+-                              << MPI_SGE_FLAGS_SHIFT;
+-      }
+-      flagsLength |= request_data_sz;
+-
+-      if ( request_data_sz > 0) {
+-              request_data = pci_alloc_consistent(
+-                  ioc->pcidev, request_data_sz, &request_data_dma);
+-
+-              if (request_data == NULL) {
+-                      dcsmisasprintk((": pci_alloc_consistent: FAILED "
+-                          "request_data_sz=%d\n", request_data_sz));
+-                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      mpt_free_msg_frame(ioc, mf);
+-                      goto cim_ssp_passthru_exit;
+-              }
+-
+-              mpt_add_sge(psge, flagsLength, request_data_dma);
+-              if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE)
+-                      memcpy(request_data, karg->bDataBuffer, request_data_sz);
+-      } else {
+-              mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
+-      }
+-
+-      if (csmisas_send_command_wait(ioc, mf, karg->IoctlHeader.Timeout) != 0) {
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_ssp_passthru_exit;
+-      }
+-
+-      memset(&karg->Status,0,sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
+-      karg->Status.bConnectionStatus = CSMI_SAS_OPEN_ACCEPT;
+-      karg->Status.bDataPresent = CSMI_SAS_SSP_NO_DATA_PRESENT;
+-      karg->Status.bStatus = GOOD;
+-      karg->Status.bResponseLength[0] = 0;
+-      karg->Status.bResponseLength[1] = 0;
+-      karg->Status.uDataBytes = request_data_sz;
+-
+-      /* process the completed Reply Message Frame */
+-      if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+-
+-              pScsiReply = (pSCSIIOReply_t ) ioc->ioctl->ReplyFrame;
+-              karg->Status.bStatus = pScsiReply->SCSIStatus;
+-              karg->Status.uDataBytes = min(le32_to_cpu(pScsiReply->TransferCount),
+-                  request_data_sz);
+-              ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+-
+-              if (pScsiReply->SCSIState ==
+-                  MPI_SCSI_STATE_AUTOSENSE_VALID) {
+-                      karg->Status.bConnectionStatus =
+-                          CSMI_SAS_SSP_SENSE_DATA_PRESENT;
+-                      karg->Status.bResponseLength[0] =
+-                              (u8)le32_to_cpu(pScsiReply->SenseCount) & 0xFF;
+-                      memcpy(karg->Status.bResponse,
+-                          ioc->ioctl->sense, le32_to_cpu(pScsiReply->SenseCount));
+-              } else if(pScsiReply->SCSIState ==
+-                  MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
+-                      karg->Status.bDataPresent =
+-                          CSMI_SAS_SSP_RESPONSE_DATA_PRESENT;
+-                      karg->Status.bResponseLength[0] =
+-                              sizeof(pScsiReply->ResponseInfo);
+-                      for (ii=0;ii<sizeof(pScsiReply->ResponseInfo);ii++) {
+-                              karg->Status.bResponse[ii] =
+-                              ((u8*)&pScsiReply->ResponseInfo)[
+-                                  (sizeof(pScsiReply->ResponseInfo)-1)-ii];
+-                      }
+-              } else if ((ioc_status != MPI_IOCSTATUS_SUCCESS) &&
+-                  (ioc_status !=  MPI_IOCSTATUS_SCSI_RECOVERED_ERROR) &&
+-                  (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
+-                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      dcsmisasprintk((": SCSI IO : "));
+-                      dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n",
+-                          pScsiReply->IOCStatus,
+-                          pScsiReply->IOCLogInfo));
+-              }
+-      }
+-
+-      if ((karg->Status.uDataBytes) && (request_data) &&
+-          (karg->Parameters.uFlags & CSMI_SAS_SSP_READ)) {
+-              if (copy_to_user((char *)uarg->bDataBuffer,
+-                  request_data, karg->Status.uDataBytes)) {
+-                      printk(KERN_ERR "%s@%d::%s - "
+-                          "Unable to write data to user %p\n",
+-                          __FILE__, __LINE__,__FUNCTION__,
+-                          (void*)karg->bDataBuffer);
+-                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              }
+-      }
+-
+- cim_ssp_passthru_exit:
+-
+-
+-      if (request_data)
+-              pci_free_consistent(ioc->pcidev, request_data_sz,
+-                  (u8 *)request_data, request_data_dma);
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, karg,
+-          offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER, bDataBuffer))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to write out csmi_sas_ssp_passthru @ %p\n",
+-                              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      free_pages((unsigned long)karg, memory_pages);
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS STP Passthru command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_stp_passthru(unsigned long arg)
+-{
+-      CSMI_SAS_STP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_STP_PASSTHRU_BUFFER     karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      pSataPassthroughRequest_t       pSataRequest;
+-      pSataPassthroughReply_t         pSataReply;
+-      MPT_FRAME_HDR                   *mf = NULL;
+-      MPIHeader_t                     *mpi_hdr;
+-      int                             iocnum;
+-      u32                             data_sz;
+-      u64                             sas_address;
+-      u16                             req_idx;
+-      char                            *psge;
+-      int                             flagsLength;
+-      void *                          request_data;
+-      dma_addr_t                      request_data_dma;
+-      u32                             request_data_sz;
+-      u8                              channel;
+-      u8                              id;
+-      u8                              volume_id;
+-      u8                              volume_bus;
+-      struct sas_device_info          *sas_info;
+-      u16                             ioc_status;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      request_data=NULL;
+-      request_data_sz = karg.Parameters.uDataLength;
+-      volume_id = 0;
+-      volume_bus = 0;
+-      channel = 0;
+-      id = 0;
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      /* Default to success.
+-       */
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-      /* Neither a phy nor a port has been selected.
+-       */
+-      if ((karg.Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
+-              (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
+-                  __FILE__,__FUNCTION__, __LINE__));
+-              goto cim_stp_passthru_exit;
+-      }
+-
+-      /* A phy has been selected. Verify that it's valid.
+-       */
+-      if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
+-
+-              /* Is the phy in range? */
+-              if (karg.Parameters.bPhyIdentifier >= ioc->num_ports) {
+-                      karg.IoctlHeader.ReturnCode =
+-                          CSMI_SAS_PHY_DOES_NOT_EXIST;
+-                      goto cim_stp_passthru_exit;
+-              }
+-      }
+-
+-      /* some checks of the incoming frame
+-       */
+-      if (request_data_sz > 0xFFFF) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - uDataLength > 0xFFFF!\n",
+-                  __FILE__, __FUNCTION__, __LINE__));
+-              goto cim_stp_passthru_exit;
+-      }
+-
+-      data_sz = sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) -
+-          sizeof(IOCTL_HEADER) - sizeof(u8*) +
+-          request_data_sz;
+-
+-      if ( data_sz > karg.IoctlHeader.Length ) {
+-              karg.IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - expected datalen incorrect!\n",
+-                  __FILE__, __FUNCTION__,__LINE__));
+-              goto cim_stp_passthru_exit;
+-      }
+-
+-
+-      /* we will use SAS address to resolve the scsi adddressing
+-       */
+-      memcpy(&sas_address, karg.Parameters.bDestinationSASAddress,
+-          sizeof(u64));
+-      sas_address = reverse_byte_order64(sas_address);
+-
+-      /* Search the list for the matching SAS address.
+-       */
+-      sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
+-      if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume) {
+-              /*
+-               *Invalid SAS address
+-               */
+-              karg.IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s()"
+-                  " @%d - couldn't find associated SASAddress=%llX!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, sas_address));
+-              goto cim_stp_passthru_exit;
+-      }
+-
+-      id = sas_info->fw.id;
+-      channel = sas_info->fw.channel;
+-
+-      /* check that this is an STP or SATA target device
+-       */
+-      if ( !(sas_info->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET ) &&
+-           !(sas_info->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE )) {
+-              karg.IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              goto cim_stp_passthru_exit;
+-      }
+-
+-      /* Get a free request frame and save the message context.
+-       */
+-      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-              dcsmisasprintk((": no msg frames!\n"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_stp_passthru_exit;
+-        }
+-
+-      mpi_hdr = (MPIHeader_t *) mf;
+-      pSataRequest = (pSataPassthroughRequest_t) mf;
+-      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-
+-      memset(pSataRequest,0,sizeof(pSataPassthroughRequest_t));
+-
+-      pSataRequest->TargetID = id;
+-      pSataRequest->Bus = channel;
+-      pSataRequest->Function = MPI_FUNCTION_SATA_PASSTHROUGH;
+-      pSataRequest->PassthroughFlags = cpu_to_le16(karg.Parameters.uFlags);
+-      pSataRequest->ConnectionRate = karg.Parameters.bConnectionRate;
+-      pSataRequest->MsgContext = mpi_hdr->MsgContext;
+-      pSataRequest->DataLength = cpu_to_le32(request_data_sz);
+-      pSataRequest->MsgFlags = 0;
+-      memcpy( pSataRequest->CommandFIS,karg.Parameters.bCommandFIS, 20);
+-
+-      psge = (char *)&pSataRequest->SGL;
+-      if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) {
+-              flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
+-      } else if (karg.Parameters.uFlags & CSMI_SAS_STP_READ) {
+-              flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
+-      }else {
+-              flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+-                              MPI_SGE_FLAGS_DIRECTION |
+-                              mpt_addr_size() )
+-                              << MPI_SGE_FLAGS_SHIFT;
+-      }
+-
+-      flagsLength |= request_data_sz;
+-      if (request_data_sz > 0) {
+-              request_data = pci_alloc_consistent(
+-                  ioc->pcidev, request_data_sz, &request_data_dma);
+-
+-              if (request_data == NULL) {
+-                      dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      mpt_free_msg_frame(ioc, mf);
+-                      goto cim_stp_passthru_exit;
+-              }
+-
+-              mpt_add_sge(psge, flagsLength, request_data_dma);
+-              if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) {
+-                      if (copy_from_user(request_data,
+-                          karg.bDataBuffer,
+-                          request_data_sz)) {
+-                              printk(KERN_ERR
+-                                  "%s::%s() @%d - Unable to read user data "
+-                                  "struct @ %p\n",
+-                                  __FILE__, __FUNCTION__, __LINE__,
+-                                  (void*)karg.bDataBuffer);
+-                              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                              mpt_free_msg_frame(ioc, mf);
+-                              goto cim_stp_passthru_exit;
+-                      }
+-              }
+-      } else {
+-              mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
+-      }
+-
+-      if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_stp_passthru_exit;
+-      }
+-
+-      memset(&karg.Status,0,sizeof(CSMI_SAS_STP_PASSTHRU_STATUS));
+-
+-      if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) {
+-              dcsmisasprintk((": STP Passthru: oh no, there is no reply!!"));
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_stp_passthru_exit;
+-      }
+-
+-      /* process the completed Reply Message Frame */
+-      pSataReply = (pSataPassthroughReply_t ) ioc->ioctl->ReplyFrame;
+-      ioc_status = le16_to_cpu(pSataReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+-
+-      if (ioc_status != MPI_IOCSTATUS_SUCCESS &&
+-          ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              dcsmisasprintk((": STP Passthru: "));
+-              dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
+-                  le16_to_cpu(pSataReply->IOCStatus),
+-                  le32_to_cpu(pSataReply->IOCLogInfo),
+-                  pSataReply->SASStatus));
+-      }
+-
+-      karg.Status.bConnectionStatus =
+-          map_sas_status_to_csmi(pSataReply->SASStatus);
+-
+-      memcpy(karg.Status.bStatusFIS,pSataReply->StatusFIS, 20);
+-
+-      /*
+-       * for now, just zero out uSCR array,
+-       * then copy the one dword returned
+-       * in the reply frame into uSCR[0]
+-       */
+-      memset( karg.Status.uSCR, 0, 64);
+-      karg.Status.uSCR[0] = le32_to_cpu(pSataReply->StatusControlRegisters);
+-
+-      if((le32_to_cpu(pSataReply->TransferCount)) && (request_data) &&
+-          (karg.Parameters.uFlags & CSMI_SAS_STP_READ)) {
+-              karg.Status.uDataBytes =
+-                  min(le32_to_cpu(pSataReply->TransferCount),request_data_sz);
+-              if (copy_to_user((char *)uarg->bDataBuffer,
+-                  request_data, karg.Status.uDataBytes)) {
+-                      printk(KERN_ERR "%s::%s() @%d - "
+-                          "Unable to write data to user %p\n",
+-                          __FILE__, __FUNCTION__, __LINE__,
+-                          (void*)karg.bDataBuffer);
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              }
+-      }
+-
+- cim_stp_passthru_exit:
+-
+-      if (request_data)
+-              pci_free_consistent(ioc->pcidev, request_data_sz,
+-                  (u8 *)request_data, request_data_dma);
+-
+-      /* Copy th data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-          offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER,bDataBuffer))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to write out csmi_sas_ssp_passthru @ %p\n",
+-                              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk((": %s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Firmware Download command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_firmware_download(unsigned long arg)
+-{
+-      CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER        karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      int                             iocnum;
+-      pMpiFwHeader_t                  pFwHeader=NULL;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg,
+-              sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_firmware_download struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      /* Default to success.*/
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-      karg.Information.usStatus = CSMI_SAS_FWD_SUCCESS;
+-      karg.Information.usSeverity = CSMI_SAS_FWD_INFORMATION;
+-
+-      /* some checks of the incoming frame */
+-      if ((karg.Information.uBufferLength +
+-          sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD)) >
+-          karg.IoctlHeader.Length) {
+-              karg.IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
+-              goto cim_firmware_download_exit;
+-      }
+-
+-      if ( karg.Information.uDownloadFlags &
+-          (CSMI_SAS_FWD_SOFT_RESET | CSMI_SAS_FWD_VALIDATE)) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
+-              karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
+-              goto cim_firmware_download_exit;
+-      }
+-
+-      /* now we need to alloc memory so we can pull in the
+-       * fw image attached to end of incoming packet.
+-       */
+-      pFwHeader = kmalloc(karg.Information.uBufferLength, GFP_KERNEL);
+-      if (!pFwHeader){
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
+-              karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
+-              goto cim_firmware_download_exit;
+-      }
+-      memset(pFwHeader, 0, sizeof(*pFwHeader));
+-
+-      if (copy_from_user(pFwHeader, uarg->bDataBuffer,
+-              karg.Information.uBufferLength)) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in pFwHeader @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if ( !((pFwHeader->Signature0 == MPI_FW_HEADER_SIGNATURE_0) &&
+-          (pFwHeader->Signature1 == MPI_FW_HEADER_SIGNATURE_1) &&
+-          (pFwHeader->Signature2 == MPI_FW_HEADER_SIGNATURE_2))) {
+-              // the signature check failed
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
+-              karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
+-              goto cim_firmware_download_exit;
+-      }
+-
+-      if ( mptctl_do_fw_download(karg.IoctlHeader.IOControllerNumber,
+-          uarg->bDataBuffer, karg.Information.uBufferLength)
+-          != 0) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
+-              karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
+-              goto cim_firmware_download_exit;
+-      }
+-
+-      if((karg.Information.uDownloadFlags & CSMI_SAS_FWD_SOFT_RESET) ||
+-          (karg.Information.uDownloadFlags & CSMI_SAS_FWD_HARD_RESET)) {
+-              if (mpt_HardResetHandler(ioc, CAN_SLEEP) != 0) {
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
+-                      karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
+-              }
+-      }
+-
+- cim_firmware_download_exit:
+-
+-      if(pFwHeader)
+-              kfree(pFwHeader);
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-                              sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to write out csmi_sas_firmware_download @ %p\n",
+-                              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get RAID Info command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_raid_info(unsigned long arg)
+-{
+-      CSMI_SAS_RAID_INFO_BUFFER __user *uarg =  (void __user *) arg;
+-      CSMI_SAS_RAID_INFO_BUFFER        karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      int                             iocnum;
+-      u32                             raidFlags;
+-      u8                              maxRaidTypes;
+-      u8                              maxDrivesPerSet;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_get_raid_info struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-      if (!ioc->raid_data.pIocPg2)
+-              goto csmisas_get_raid_info_out;
+-      karg.Information.uNumRaidSets =
+-          ioc->raid_data.pIocPg2->NumActiveVolumes;
+-      karg.Information.uMaxRaidSets = ioc->raid_data.pIocPg2->MaxVolumes;
+-      if( ioc->raid_data.pIocPg6 ) {
+-              // get absolute maximum for all RAID sets
+-              maxDrivesPerSet = ioc->raid_data.pIocPg6->MaxDrivesIS;
+-              maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIM,
+-                  maxDrivesPerSet);
+-              maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIME,
+-                  maxDrivesPerSet);
+-              karg.Information.uMaxDrivesPerSet = maxDrivesPerSet;
+-      }
+-      else
+-              karg.Information.uMaxDrivesPerSet = 8;
+-      // For bMaxRaidSets, count bits set in bits 0-6 of CapabilitiesFlags
+-      raidFlags = ioc->raid_data.pIocPg2->CapabilitiesFlags & 0x0000007F;
+-      for( maxRaidTypes=0; raidFlags; maxRaidTypes++ )
+-              raidFlags &= raidFlags - 1;
+-      karg.Information.bMaxRaidTypes = maxRaidTypes;
+-      // ulMinRaidSetBlocks hard coded to 1MB until available from config page
+-      karg.Information.ulMinRaidSetBlocks.uLowPart = 2048;
+-      karg.Information.ulMinRaidSetBlocks.uHighPart = 0;
+-      karg.Information.ulMaxRaidSetBlocks.uLowPart = 0xffffffff;
+-      if( ioc->raid_data.pIocPg2->CapabilitiesFlags &
+-          MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING )
+-              karg.Information.ulMaxRaidSetBlocks.uHighPart = 0xffffffff;
+-      else
+-              karg.Information.ulMaxRaidSetBlocks.uHighPart = 0;
+-      karg.Information.uMaxPhysicalDrives =
+-          ioc->raid_data.pIocPg2->MaxPhysDisks;
+-      karg.Information.uMaxExtents = 1;
+-      karg.Information.uMaxModules = 0;
+-      karg.Information.uMaxTransformationMemory = 0;
+-      karg.Information.uChangeCount = ioc->csmi_change_count;
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-csmisas_get_raid_info_out:
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-                              sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to write out csmi_sas_get_raid_info @ %p\n",
+-                              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- *    csmisas_do_raid - Format and Issue a RAID volume request message.
+- *    @ioc: Pointer to MPT_ADAPTER structure
+- *    @action: What do be done.
+- *    @PhysDiskNum: Logical target id.
+- *    @VolumeBus: Target locations bus.
+- *    @VolumeId: Volume id
+- *
+- *    Returns: < 0 on a fatal error
+- *            0 on success
+- *
+- *    Remark: Wait to return until reply processed by the ISR.
+- **/
+-static int
+-csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, u8 VolumeId, pMpiRaidActionReply_t reply)
+-{
+-      MpiRaidActionRequest_t  *pReq;
+-      MpiRaidActionReply_t    *pReply;
+-      MPT_FRAME_HDR           *mf;
+-
+-      /* Get and Populate a free Frame
+-       */
+-      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-              dcsmisasprintk((": no msg frames!\n"));
+-              return -EAGAIN;
+-      }
+-      pReq = (MpiRaidActionRequest_t *)mf;
+-      pReq->Action = action;
+-      pReq->Reserved1 = 0;
+-      pReq->ChainOffset = 0;
+-      pReq->Function = MPI_FUNCTION_RAID_ACTION;
+-      pReq->VolumeID = VolumeId;
+-      pReq->VolumeBus = VolumeBus;
+-      pReq->PhysDiskNum = PhysDiskNum;
+-      pReq->MsgFlags = 0;
+-      pReq->Reserved2 = 0;
+-      pReq->ActionDataWord = 0; /* Reserved for this action */
+-      //pReq->ActionDataSGE = 0;
+-
+-      mpt_add_sge((char *)&pReq->ActionDataSGE,
+-              MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
+-
+-      if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0)
+-              return -ENODATA;
+-
+-      if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) &&
+-          (reply != NULL)){
+-              pReply = (MpiRaidActionReply_t *)&(ioc->ioctl->ReplyFrame);
+-              memcpy(reply, pReply,
+-                      min(ioc->reply_sz,
+-                      4*pReply->MsgLength));
+-      }
+-
+-      return 0;
+-}
+-
+-/**
+- * csmisas_raid_inq
+- * @ioc = per host instance
+- * @opcode = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH or
+- *         MPI_FUNCTION_SCSI_IO_REQUEST
+- * @id = target id
+- * @bus = target bus
+- * @inq_vpd = inquiry data, returned
+- * @inq_vpd_sz = maximum size of inquiry data
+- *
+- * Return = 0(sucess), non-zero(failure)
+- **/
+-static int
+-csmisas_raid_inq(MPT_ADAPTER *ioc, u8 opcode, u8 bus, u8 id, u8 inq_vpd_page,
+-    u8 * inq_vpd, u32 inq_vpd_sz)
+-{
+-      MPT_FRAME_HDR           *mf = NULL;
+-      MPIHeader_t             *mpi_hdr;
+-      pSCSIIORequest_t        pScsiRequest;
+-      u16                     req_idx;
+-      char                    *psge;
+-      u8                      inq_vpd_cdb[6];
+-      u8                      *request_data=NULL;
+-      dma_addr_t              request_data_dma;
+-      u32                     request_data_sz;
+-      int                     rc = 0;
+-
+-      request_data_sz = inq_vpd_sz;
+-
+-      /* fill-in cdb */
+-      memset(inq_vpd_cdb, 0, sizeof(inq_vpd_cdb));
+-      inq_vpd_cdb[0] = 0x12;
+-      if (inq_vpd_page) {
+-              inq_vpd_cdb[1] = 0x01; /* evpd bit */
+-              inq_vpd_cdb[2] = inq_vpd_page;
+-      }
+-      inq_vpd_cdb[3] = (u8)(request_data_sz >> 8);
+-      inq_vpd_cdb[4] = (u8)request_data_sz;
+-
+-      /* Get a free request frame and save the message context.
+-       */
+-      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-              dcsmisasprintk((": no msg frames!\n"));
+-              goto csmisas_raid_inq_exit;
+-      }
+-
+-      mpi_hdr = (MPIHeader_t *) mf;
+-      pScsiRequest = (pSCSIIORequest_t) mf;
+-      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-
+-      memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
+-      pScsiRequest->Function = opcode;
+-      pScsiRequest->TargetID = id;
+-      pScsiRequest->Bus = bus;
+-      pScsiRequest->CDBLength = 6;
+-      pScsiRequest->DataLength = cpu_to_le32(request_data_sz);
+-      pScsiRequest->MsgContext = mpi_hdr->MsgContext;
+-      memcpy(pScsiRequest->CDB,inq_vpd_cdb,pScsiRequest->CDBLength);
+-      pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
+-      pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
+-      pScsiRequest->MsgFlags = mpt_msg_flags();
+-
+-      /* setup sense
+-       */
+-      pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
+-      pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
+-          (req_idx * MPT_SENSE_BUFFER_ALLOC));
+-
+-      request_data = pci_alloc_consistent(
+-          ioc->pcidev, request_data_sz, &request_data_dma);
+-
+-      if (request_data == NULL) {
+-              mpt_free_msg_frame(ioc, mf);
+-              rc=-1;
+-              goto csmisas_raid_inq_exit;
+-      }
+-
+-      memset(request_data,0,request_data_sz);
+-      psge = (char *)&pScsiRequest->SGL;
+-      mpt_add_sge(psge, (MPT_SGE_FLAGS_SSIMPLE_READ | 0xFC) ,
+-          request_data_dma);
+-
+-      if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0) {
+-              rc=-1;
+-              goto csmisas_raid_inq_exit;
+-      }
+-
+-      /* copy the request_data */
+-      memcpy(inq_vpd, request_data, request_data_sz);
+-
+- csmisas_raid_inq_exit:
+-
+-      if (request_data)
+-              pci_free_consistent(ioc->pcidev, request_data_sz,
+-                  request_data, request_data_dma);
+-
+-      return rc;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get RAID Config command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_raid_config(unsigned long arg)
+-{
+-      CSMI_SAS_RAID_CONFIG_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_RAID_CONFIG_BUFFER      karg,*pKarg=NULL;
+-      CONFIGPARMS                     cfg;
+-      ConfigPageHeader_t              header;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      int                             iocnum;
+-      u8                              volumeID, VolumeBus;
+-      u8                              physDiskNum, physDiskNumMax;
+-      int                             volumepage0sz = 0;
+-      int                             physdiskpage0sz = 0, ioc_page5_sz = 0;
+-      dma_addr_t                      volume0_dma, physdisk0_dma;
+-      dma_addr_t                      ioc_page5_dma = 0;
+-      pRaidVolumePage0_t              pVolume0 = NULL;
+-      pRaidPhysDiskPage0_t            pPhysDisk0 = NULL;
+-      pMpiRaidActionReply_t           pRaidActionReply = NULL;
+-      u32                             device_info = 0;
+-      pIOCPage5_t                     pIocPage5 = NULL;
+-      int                             i, idx, csmi_sas_raid_config_buffer_sz;
+-      int                             memory_pages;
+-      int                             copy_buffer_sz = 0;
+-      u64                             totalMaxLBA, tmpTotalMaxLBA;
+-      u64                             sas_address;
+-      struct sas_device_info          *sas_info;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmisas_get_raid_config struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      csmi_sas_raid_config_buffer_sz = karg.IoctlHeader.Length;
+-      memory_pages = get_order(csmi_sas_raid_config_buffer_sz);
+-      pKarg = (CSMI_SAS_RAID_CONFIG_BUFFER *)__get_free_pages(
+-              GFP_KERNEL, memory_pages);
+-      if (!pKarg){
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to malloc RAID_CONFIG_BUFFER "
+-                      "csmi_sas_raid_config_buffer_sz=%d memory_pages=%d\n",
+-                      __FILE__, __LINE__, __FUNCTION__,
+-                      csmi_sas_raid_config_buffer_sz, memory_pages);
+-              return -ENOMEM;
+-      }
+-      memset(pKarg, 0, sizeof(*pKarg));
+-
+-      if (copy_from_user(pKarg, uarg, csmi_sas_raid_config_buffer_sz)) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmisas_get_raid_config struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      if (pKarg->Configuration.uChangeCount != 0 &&
+-              pKarg->Configuration.uChangeCount != ioc->csmi_change_count ) {
+-              pKarg->IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              pKarg->Configuration.uFailureCode =
+-                  CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      if (!ioc->raid_data.pIocPg2) {
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      /*
+-       * Check to see if the input uRaidSetIndex is
+-       * greater than the number of RAID sets
+-       */
+-      if (pKarg->Configuration.uRaidSetIndex >=
+-          ioc->raid_data.pIocPg2->NumActiveVolumes) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_RAID_SET_OUT_OF_RANGE;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      /*
+-       * get RAID Volume Page 0
+-       */
+-      volumeID = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeID;
+-      VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeBus;
+-
+-      header.PageVersion = 0;
+-      header.PageLength = 0;
+-      header.PageNumber = 0;
+-      header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+-      cfg.cfghdr.hdr = &header;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = (VolumeBus << 8) + volumeID;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      if (header.PageLength == 0) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      volumepage0sz = header.PageLength * 4;
+-      pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
+-          &volume0_dma);
+-      if (!pVolume0) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-      cfg.physAddr = volume0_dma;
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) |
+-          ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32;
+-      tmpTotalMaxLBA = totalMaxLBA + 1;
+-      do_div(tmpTotalMaxLBA, 2048);
+-      pKarg->Configuration.uCapacity = tmpTotalMaxLBA;
+-      pKarg->Configuration.uStripeSize =
+-              le32_to_cpu(pVolume0->StripeSize)/2;
+-
+-      switch(pVolume0->VolumeType) {
+-      case MPI_RAID_VOL_TYPE_IS:
+-              pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_0;
+-              break;
+-      case MPI_RAID_VOL_TYPE_IME:
+-              pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_10;
+-              break;
+-      case MPI_RAID_VOL_TYPE_IM:
+-              pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_1;
+-              break;
+-      default:
+-              pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_OTHER;
+-              break;
+-      }
+-
+-      switch (pVolume0->VolumeStatus.State) {
+-      case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
+-              pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OK;
+-              break;
+-      case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
+-              /* Volume is degraded, check if Resyncing or Inactive */
+-              pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_DEGRADED;
+-              break;
+-      case MPI_RAIDVOL0_STATUS_STATE_FAILED:
+-              pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_FAILED;
+-              break;
+-      }
+-
+-      /* check flags */
+-      if (pVolume0->VolumeStatus.Flags &
+-          MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)
+-              pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OFFLINE;
+-      else if (pVolume0->VolumeStatus.Flags &
+-          MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)
+-              pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_REBUILDING;
+-
+-      pKarg->Configuration.bInformation = 0;  /* default */
+-      if(pVolume0->VolumeStatus.Flags &
+-          MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ) {
+-
+-              uint64_t        * ptrUint64;
+-              uint64_t        totalBlocks64, blocksRemaining64;
+-              uint32_t        totalBlocks32, blocksRemaining32;
+-
+-              /* get percentage complete */
+-              pRaidActionReply = kmalloc( sizeof(MPI_RAID_VOL_INDICATOR) +
+-                  offsetof(MSG_RAID_ACTION_REPLY,ActionData),
+-                  GFP_KERNEL);
+-
+-              if (!pRaidActionReply){
+-                      printk(KERN_ERR "%s@%d::%s() - "
+-                          "Unable to malloc @ %p\n",
+-                          __FILE__, __LINE__, __FUNCTION__,pKarg);
+-                      goto cim_get_raid_config_exit;
+-              }
+-              memset(pRaidActionReply, 0, sizeof(*pRaidActionReply));
+-
+-              csmisas_do_raid(ioc,
+-                  MPI_RAID_ACTION_INDICATOR_STRUCT,
+-                  0, VolumeBus, volumeID, pRaidActionReply);
+-
+-              ptrUint64       = (uint64_t *)&pRaidActionReply->ActionData;
+-              totalBlocks64     = *ptrUint64;
+-              ptrUint64++;
+-              blocksRemaining64 = *ptrUint64;
+-              while(totalBlocks64 > 0xFFFFFFFFUL){
+-                      totalBlocks64 = totalBlocks64 >> 1;
+-                      blocksRemaining64 = blocksRemaining64 >> 1;
+-              }
+-              totalBlocks32 = (uint32_t)totalBlocks64;
+-              blocksRemaining32 = (uint32_t)blocksRemaining64;
+-
+-              if(totalBlocks32)
+-                      pKarg->Configuration.bInformation =
+-                          (totalBlocks32 - blocksRemaining32) /
+-                          (totalBlocks32 / 100);
+-
+-              kfree(pRaidActionReply);
+-      }
+-
+-      /* fill-in more information depending on data type */
+-      if (pKarg->Configuration.bDataType ==
+-          CSMI_SAS_RAID_DATA_ADDITIONAL_DATA) {
+-              pKarg->Configuration.Data->bLabel[0] = '\0';
+-              pKarg->Configuration.Data->bRaidSetLun[1] = 0;
+-              pKarg->Configuration.Data->bWriteProtection =
+-                      CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN;
+-              pKarg->Configuration.Data->bCacheSetting =
+-                      CSMI_SAS_RAID_SET_CACHE_UNKNOWN;
+-              pKarg->Configuration.Data->bCacheRatio = 0;
+-              pKarg->Configuration.Data->usBlockSize = 512;
+-              pKarg->Configuration.Data->ulRaidSetExtentOffset.uLowPart = 0;
+-              pKarg->Configuration.Data->ulRaidSetExtentOffset.uHighPart = 0;
+-              pKarg->Configuration.Data->ulRaidSetBlocks.uLowPart =
+-                  le32_to_cpu(pVolume0->MaxLBA);
+-              pKarg->Configuration.Data->ulRaidSetBlocks.uHighPart =
+-                  le32_to_cpu(pVolume0->MaxLBAHigh);
+-              if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS ||
+-                  pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME ) {
+-                      pKarg->Configuration.Data->uStripeSizeInBlocks =
+-                          le32_to_cpu(pVolume0->StripeSize);
+-              } else {
+-                      pKarg->Configuration.Data->uStripeSizeInBlocks = 0;
+-              }
+-              pKarg->Configuration.Data->uSectorsPerTrack = 128;
+-              for (i=0; i<16; i++) {
+-                      // unsupported
+-                      pKarg->Configuration.Data->bApplicationScratchPad[i] =
+-                          0xFF;
+-              }
+-              pKarg->Configuration.Data->uNumberOfHeads = 16;
+-
+-              tmpTotalMaxLBA = totalMaxLBA;
+-              do_div(tmpTotalMaxLBA,
+-                  (pKarg->Configuration.Data->uNumberOfHeads *
+-                   pKarg->Configuration.Data->uSectorsPerTrack));
+-              pKarg->Configuration.Data->uNumberOfTracks = tmpTotalMaxLBA;
+-              pKarg->Configuration.bDriveCount = 1;
+-      } else if ( pKarg->Configuration.bDataType ==
+-          CSMI_SAS_RAID_DATA_DEVICE_ID ) {
+-              /* Send inquiry to get VPD Page 0x83 */
+-              u32 vpd_page_sz;
+-              vpd_page_sz = csmi_sas_raid_config_buffer_sz -
+-                  offsetof(CSMI_SAS_RAID_CONFIG,DeviceId);
+-              if (csmisas_raid_inq(ioc, MPI_FUNCTION_SCSI_IO_REQUEST,
+-                      VolumeBus, volumeID, 0x83,
+-                      (u8*)&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage,
+-                      vpd_page_sz) != 0) {
+-                      pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto cim_get_raid_config_exit;
+-              }
+-              pKarg->Configuration.bDriveCount = 1;
+-      }
+-
+-      if (pKarg->Configuration.bDataType != CSMI_SAS_RAID_DATA_DRIVES) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      /* suppress drive information */
+-      if (pKarg->Configuration.bDriveCount ==
+-              CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      /* get hotspare info, used later in this function */
+-      if (pVolume0->VolumeSettings.HotSparePool) {
+-              /* Read and save IOC Page 5
+-               */
+-              header.PageVersion = 0;
+-              header.PageLength = 0;
+-              header.PageNumber = 5;
+-              header.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-              cfg.cfghdr.hdr = &header;
+-              cfg.physAddr = -1;
+-              cfg.pageAddr = 0;
+-              cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-              cfg.dir = 0;
+-              cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-              if ((mpt_config(ioc, &cfg) == 0) && (header.PageLength)) {
+-                      ioc_page5_sz = header.PageLength * 4;
+-                      pIocPage5 = pci_alloc_consistent(ioc->pcidev,
+-                          ioc_page5_sz,
+-                          &ioc_page5_dma);
+-                      memset(pIocPage5,0,ioc_page5_sz);
+-                      if (ioc_page5_dma) {
+-                              cfg.physAddr = ioc_page5_dma;
+-                              cfg.action =
+-                                  MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-                              mpt_config(ioc, &cfg);
+-                      }
+-              }
+-      }
+-
+-      /*
+-       * get RAID Physical Disk Page 0
+-       */
+-      header.PageVersion = 0;
+-      header.PageLength = 0;
+-      header.PageNumber = 0;
+-      header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+-      cfg.cfghdr.hdr = &header;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = 0;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      if (header.PageLength == 0) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_raid_config_exit;
+-      }
+-
+-      physdiskpage0sz = header.PageLength * 4;
+-      pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
+-          &physdisk0_dma);
+-      if (!pPhysDisk0) {
+-              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_get_raid_config_exit;
+-      }
+-      cfg.physAddr = physdisk0_dma;
+-
+-      physDiskNumMax = (csmi_sas_raid_config_buffer_sz -
+-          offsetof(CSMI_SAS_RAID_CONFIG,Drives))
+-          / sizeof(CSMI_SAS_RAID_DRIVES);
+-
+-      pKarg->Configuration.bDriveCount=0;
+-
+-      tmpTotalMaxLBA = totalMaxLBA;
+-      if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS) {
+-              do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
+-              dcsmisasprintk(("IS Volume tmpTotalMaxLBA=%llX\n",
+-              (unsigned long long)tmpTotalMaxLBA));
+-      }
+-      else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME) {
+-              do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks * 2);
+-              dcsmisasprintk(("IME Volume tmpTotalMaxLBA=%llX\n",
+-              (unsigned long long)tmpTotalMaxLBA));
+-      } else {
+-              dcsmisasprintk(("IM Volume tmpTotalMaxLBA=%llX\n",
+-              (unsigned long long)tmpTotalMaxLBA));
+-      }
+-
+-      for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
+-
+-              physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum;
+-              cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-              cfg.pageAddr = physDiskNum;
+-              if (mpt_config(ioc, &cfg) != 0){
+-                      pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto cim_get_raid_config_exit;
+-              }
+-
+-              /* Search the list for the matching SAS address. */
+-              sas_info = csmisas_get_device_component_by_fw(ioc, pPhysDisk0->PhysDiskBus,
+-                  pPhysDisk0->PhysDiskID);
+-
+-              if (!sas_info)
+-                      continue;
+-
+-              sas_address = reverse_byte_order64(sas_info->sas_address);
+-              memcpy(pKarg->Configuration.Drives[i].bSASAddress,
+-                 &sas_address,sizeof(u64));
+-              if (!device_info)
+-                      device_info = sas_info->device_info;
+-
+-              memcpy(pKarg->Configuration.Drives[i].bModel,
+-                  pPhysDisk0->InquiryData.VendorID,
+-                  offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
+-              memcpy(pKarg->Configuration.Drives[i].bFirmware,
+-                      pPhysDisk0->InquiryData.ProductRevLevel,
+-                      sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
+-              if (csmisas_is_sata(pPhysDisk0)) {
+-                      memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
+-                              &pPhysDisk0->ExtDiskIdentifier[4],
+-                              4);
+-                      memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
+-                              &pPhysDisk0->DiskIdentifier,
+-                              sizeof(pPhysDisk0->DiskIdentifier));
+-              } else {
+-                      memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
+-                              pPhysDisk0->DiskIdentifier,
+-                              sizeof(pPhysDisk0->DiskIdentifier));
+-              }
+-
+-              pKarg->Configuration.Drives[i].bDriveUsage =
+-                  (pPhysDisk0->PhysDiskStatus.Flags &
+-                  MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) ?
+-                  CSMI_SAS_DRIVE_CONFIG_NOT_USED :
+-                  CSMI_SAS_DRIVE_CONFIG_MEMBER;
+-
+-              pKarg->Configuration.Drives[i].bDriveStatus =
+-                  CSMI_SAS_DRIVE_STATUS_OK;
+-              if (pPhysDisk0->PhysDiskStatus.State ==
+-                  MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED) {
+-                      pKarg->Configuration.Drives[i].bDriveStatus =
+-                          CSMI_SAS_DRIVE_STATUS_OFFLINE;
+-              } else if(pPhysDisk0->PhysDiskStatus.State) {
+-                      pKarg->Configuration.Drives[i].bDriveStatus =
+-                          CSMI_SAS_DRIVE_STATUS_FAILED;
+-                      if(pKarg->Configuration.bStatus ==
+-                          CSMI_SAS_RAID_SET_STATUS_DEGRADED)
+-                              pKarg->Configuration.bInformation = i;
+-              } else if((pVolume0->VolumeStatus.Flags &
+-                  MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) &&
+-                  (pPhysDisk0->PhysDiskStatus.Flags &
+-                  MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
+-                      pKarg->Configuration.Drives[i].bDriveStatus =
+-                          CSMI_SAS_DRIVE_STATUS_REBUILDING;
+-              else if(pPhysDisk0->ErrorData.SmartCount ||
+-                  (pPhysDisk0->PhysDiskStatus.Flags &
+-                  MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
+-                      pKarg->Configuration.Drives[i].bDriveStatus =
+-                      CSMI_SAS_DRIVE_STATUS_DEGRADED;
+-
+-              memset(pKarg->Configuration.Drives[i].bSASLun,
+-                  0, sizeof(pKarg->Configuration.Drives[i].bSASLun));
+-              if (csmisas_is_sata(pPhysDisk0)) {
+-                      pKarg->Configuration.Drives[i].bDriveType =
+-                      CSMI_SAS_DRIVE_TYPE_SATA;
+-              } else { /* drive in a volume can only be SAS/SATA */
+-                      pKarg->Configuration.Drives[i].bDriveType =
+-                              CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
+-              }
+-
+-              pKarg->Configuration.Drives[i].usBlockSize = 512;
+-                      pKarg->Configuration.Drives[i].uDriveIndex =
+-                          pPhysDisk0->PhysDiskNum;
+-              pKarg->Configuration.Drives[i].ulTotalUserBlocks.uLowPart =
+-                  (u32)tmpTotalMaxLBA;
+-              pKarg->Configuration.Drives[i].ulTotalUserBlocks.uHighPart =
+-                  (u32)(tmpTotalMaxLBA >> 32);
+-              pKarg->Configuration.bDriveCount++;
+-      }
+-
+-      /* adding hot spare info at the end */
+-      if ((pVolume0->VolumeSettings.HotSparePool) && (pIocPage5) &&
+-          (pVolume0->VolumeType != MPI_RAID_VOL_TYPE_IS)) {
+-              for (idx = 0, i = pVolume0->NumPhysDisks ;
+-                  idx < pIocPage5->NumHotSpares ; idx++) {
+-                      if (i >= physDiskNumMax)
+-                              break;
+-                      if ((pVolume0->VolumeSettings.HotSparePool &
+-                          pIocPage5->HotSpare[idx].HotSparePool) == 0)
+-                              continue;
+-                      if(pIocPage5->HotSpare[idx].Flags !=
+-                          MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE)
+-                          continue;
+-                      physDiskNum = pIocPage5->HotSpare[idx].PhysDiskNum;
+-                      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-                      cfg.pageAddr = physDiskNum;
+-                      if (mpt_config(ioc, &cfg) != 0)
+-                              continue;
+-
+-                      /* Search the list for the matching SAS address. */
+-                      sas_info = csmisas_get_device_component_by_fw(ioc,
+-                          pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
+-
+-                      if (!sas_info)
+-                              continue;
+-
+-                      sas_address = reverse_byte_order64(sas_info->sas_address);
+-                      memcpy(pKarg->Configuration.Drives[i].bSASAddress,
+-                         &sas_address,sizeof(u64));
+-
+-                      /* don't mix SSP hot spare
+-                       * in SATA volume
+-                       */
+-                      if (!csmisas_is_sata(pPhysDisk0) &&
+-                          (device_info &
+-                          MPI_SAS_DEVICE_INFO_SATA_DEVICE))
+-                              continue;
+-
+-                      /* don't mix SATA hot spare
+-                       * in SSP volume
+-                       */
+-                      if (csmisas_is_sata(pPhysDisk0) &&
+-                          (device_info &
+-                          MPI_SAS_DEVICE_INFO_SSP_TARGET))
+-                              continue;
+-
+-                      /* capacity check for IM volumes*/
+-                      if ((pVolume0->VolumeType ==
+-                          MPI_RAID_VOL_TYPE_IM) &&
+-                          (totalMaxLBA +
+-                          (64*2*1024) /* metadata = 64MB*/ >
+-                          le32_to_cpu(pPhysDisk0->MaxLBA)))
+-                              continue;
+-
+-                      tmpTotalMaxLBA = totalMaxLBA;
+-                      do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
+-                      /* capacity check for IME volumes*/
+-                      if ((pVolume0->VolumeType ==
+-                              MPI_RAID_VOL_TYPE_IME) &&
+-                          ((tmpTotalMaxLBA * 2) +
+-                           (64*2*1024 ) /*metadata = 64MB*/ >
+-                          le32_to_cpu(pPhysDisk0->MaxLBA)))
+-                              break;
+-
+-                      /* capacity check for IME volumes*/
+-                      if ((pVolume0->VolumeType ==
+-                          MPI_RAID_VOL_TYPE_IME) &&
+-                          (((totalMaxLBA +
+-                          pVolume0->NumPhysDisks) * 2) +
+-                          (64*2*1024 ) /*metadata = 64MB*/ >
+-                          le32_to_cpu(pPhysDisk0->MaxLBA)))
+-                              continue;
+-
+-                      memcpy(pKarg->Configuration.Drives[i].bModel,
+-                          pPhysDisk0->InquiryData.VendorID,
+-                          offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
+-                      memcpy(pKarg->Configuration.Drives[i].bFirmware,
+-                              pPhysDisk0->InquiryData.ProductRevLevel,
+-                              sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
+-                      if (csmisas_is_sata(pPhysDisk0)) {
+-                              memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
+-                                      &pPhysDisk0->ExtDiskIdentifier[4],
+-                                      4);
+-                              memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
+-                                      &pPhysDisk0->DiskIdentifier,
+-                                      sizeof(pPhysDisk0->DiskIdentifier));
+-                      } else {
+-                              memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
+-                                      pPhysDisk0->DiskIdentifier,
+-                                      sizeof(pPhysDisk0->DiskIdentifier));
+-                      }
+-                      pKarg->Configuration.Drives[i].bDriveStatus =
+-                          CSMI_SAS_DRIVE_STATUS_OK;
+-                      if(pPhysDisk0->PhysDiskStatus.State)
+-                              pKarg->Configuration.Drives[i].bDriveStatus =
+-                                  CSMI_SAS_DRIVE_STATUS_FAILED;
+-                      else if(pPhysDisk0->ErrorData.SmartCount)
+-                              pKarg->Configuration.Drives[i].bDriveStatus =
+-                                  CSMI_SAS_DRIVE_STATUS_DEGRADED;
+-                      pKarg->Configuration.Drives[i].bDriveUsage =
+-                          CSMI_SAS_DRIVE_CONFIG_SPARE;
+-                      pKarg->Configuration.Drives[i].usBlockSize = 512;
+-                      pKarg->Configuration.Drives[i].uDriveIndex =
+-                          pPhysDisk0->PhysDiskNum;
+-                      if (csmisas_is_sata(pPhysDisk0)) {
+-                              pKarg->Configuration.Drives[i].bDriveType =
+-                              CSMI_SAS_DRIVE_TYPE_SATA;
+-                      } else { /* drive in a volume can only be SAS/SATA */
+-                              pKarg->Configuration.Drives[i].bDriveType =
+-                                      CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
+-                      }
+-
+-                      i++;
+-                      pKarg->Configuration.bDriveCount++;
+-              }
+-      }
+-
+-      // Only return data on the first 240 drives
+-      if( pKarg->Configuration.bDriveCount > 0xF0 )
+-              pKarg->Configuration.bDriveCount =
+-                  CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG;
+-
+-      pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+- cim_get_raid_config_exit:
+-
+-      if (pVolume0 != NULL)
+-              pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
+-                  volume0_dma);
+-
+-      if(pPhysDisk0 != NULL)
+-              pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
+-                  physdisk0_dma);
+-
+-      if(pIocPage5 != NULL)
+-              pci_free_consistent(ioc->pcidev, ioc_page5_sz, pIocPage5,
+-                  ioc_page5_dma);
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-
+-      /* find the buffer size to copy depending on how much is filled-in */
+-      switch (pKarg->Configuration.bDataType) {
+-      case CSMI_SAS_RAID_DATA_ADDITIONAL_DATA:
+-              copy_buffer_sz = sizeof(IOCTL_HEADER) +
+-                  offsetof(CSMI_SAS_RAID_CONFIG,Data) +
+-                  sizeof(CSMI_SAS_RAID_SET_ADDITIONAL_DATA);
+-              break;
+-      case CSMI_SAS_RAID_DATA_DRIVES:
+-              if (pKarg->Configuration.bDriveCount ==
+-                  CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED)
+-                      copy_buffer_sz = sizeof(IOCTL_HEADER) +
+-                          offsetof(CSMI_SAS_RAID_CONFIG,Drives);
+-              else
+-                      copy_buffer_sz = sizeof(IOCTL_HEADER) +
+-                          offsetof(CSMI_SAS_RAID_CONFIG,Drives) +
+-                          (pKarg->Configuration.bDriveCount *
+-                          sizeof(CSMI_SAS_RAID_DRIVES));
+-              break;
+-      case CSMI_SAS_RAID_DATA_DEVICE_ID:
+-              copy_buffer_sz = csmi_sas_raid_config_buffer_sz;
+-              break;
+-      }
+-
+-      if (copy_to_user((char *)arg, pKarg, copy_buffer_sz)) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                     "Unable to write out csmi_sas_get_raid_config @ %p\n",
+-                         __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      free_pages((unsigned long)pKarg, memory_pages);
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get RAID Features command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_raid_features(unsigned long arg)
+-{
+-      CSMI_SAS_RAID_FEATURES_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_RAID_FEATURES_BUFFER karg, *pKarg=NULL;
+-      int csmi_sas_raid_features_buffer_sz, iocnum;
+-      int                             memory_pages;
+-      MPT_ADAPTER             *ioc = NULL;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      csmi_sas_raid_features_buffer_sz = karg.IoctlHeader.Length;
+-      memory_pages = get_order(csmi_sas_raid_features_buffer_sz);
+-      pKarg = (CSMI_SAS_RAID_FEATURES_BUFFER *)__get_free_pages(
+-              GFP_KERNEL, memory_pages);
+-      if (!pKarg){
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to malloc RAID_FEATURES_BUFFER "
+-                      "csmi_sas_raid_features_buffer_sz=%d memory_pages=%d\n",
+-                      __FILE__, __LINE__, __FUNCTION__,
+-                      csmi_sas_raid_features_buffer_sz, memory_pages);
+-              return -ENOMEM;
+-      }
+-      memset(pKarg, 0, sizeof(*pKarg));
+-
+-      if (copy_from_user(pKarg, uarg, csmi_sas_raid_features_buffer_sz)) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      if (pKarg->Information.uChangeCount != 0 &&
+-          pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
+-              pKarg->IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              pKarg->Information.uFailureCode =
+-                  CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
+-              goto cim_get_raid_features_exit;
+-      }
+-
+-      pKarg->Information.uFeatures = CSMI_SAS_RAID_FEATURE_REBUILD |
+-          CSMI_SAS_RAID_FEATURE_SURFACE_SCAN |
+-          CSMI_SAS_RAID_FEATURE_SPARES_SHARED;
+-      pKarg->Information.bDefaultTransformPriority =
+-          CSMI_SAS_PRIORITY_UNKNOWN;
+-      pKarg->Information.bTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN;
+-      pKarg->Information.bDefaultRebuildPriority = CSMI_SAS_PRIORITY_UNKNOWN;
+-      pKarg->Information.bRebuildPriority =
+-          pKarg->Information.bDefaultRebuildPriority;
+-      pKarg->Information.bDefaultSurfaceScanPriority =
+-          CSMI_SAS_PRIORITY_UNKNOWN;
+-      pKarg->Information.bSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN;
+-      pKarg->Information.uRaidSetTransformationRules = 0;
+-
+-       /* IS */
+-      pKarg->Information.RaidType[0].bRaidType = CSMI_SAS_RAID_TYPE_0;
+-      pKarg->Information.RaidType[0].uSupportedStripeSizeMap = 0x80;
+-
+-      /* IM */
+-      pKarg->Information.RaidType[1].bRaidType = CSMI_SAS_RAID_TYPE_1;
+-      pKarg->Information.RaidType[1].uSupportedStripeSizeMap = 0;
+-
+-      /* IME */
+-      pKarg->Information.RaidType[2].bRaidType = CSMI_SAS_RAID_TYPE_1E;
+-      pKarg->Information.RaidType[2].uSupportedStripeSizeMap = 0x80;
+-
+-      pKarg->Information.RaidType[3].bRaidType = CSMI_SAS_RAID_TYPE_END;
+-      pKarg->Information.bCacheRatiosSupported[0] =
+-          CSMI_SAS_RAID_CACHE_RATIO_END;
+-
+- cim_get_raid_features_exit:
+-
+-      /*
+-       * Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, pKarg,
+-          sizeof(CSMI_SAS_RAID_FEATURES_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-              "Unable to write out csmi_sas_get_raid_features @ %p\n",
+-              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      free_pages((unsigned long)pKarg, memory_pages);
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Set RAID Control command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_set_raid_control(unsigned long arg)
+-{
+-      CSMI_SAS_RAID_CONTROL_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_RAID_CONTROL_BUFFER karg, *pKarg=NULL;
+-      int csmi_sas_raid_control_buffer_sz, iocnum;
+-      int                             memory_pages;
+-      MPT_ADAPTER     *ioc = NULL;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_set_raid_control struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      csmi_sas_raid_control_buffer_sz = karg.IoctlHeader.Length;
+-      memory_pages = get_order(csmi_sas_raid_control_buffer_sz);
+-      pKarg = (CSMI_SAS_RAID_CONTROL_BUFFER *)__get_free_pages(
+-              GFP_KERNEL, memory_pages);
+-      if (!pKarg){
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to malloc RAID_CONTROL_BUFFER "
+-                      "csmi_sas_raid_control_buffer_sz=%d memory_pages=%d\n",
+-                      __FILE__, __LINE__, __FUNCTION__,
+-                      csmi_sas_raid_control_buffer_sz, memory_pages);
+-              return -ENOMEM;
+-      }
+-      memset(pKarg, 0, sizeof(*pKarg));
+-
+-      if (copy_from_user(pKarg, uarg, csmi_sas_raid_control_buffer_sz)) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_set_raid_control struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      if (pKarg->Information.uChangeCount != 0 &&
+-              pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
+-              pKarg->IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              pKarg->Information.uFailureCode =
+-                  CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
+-              goto cim_set_raid_control_exit;
+-      }
+-
+-      if (pKarg->Information.bTransformPriority !=
+-          CSMI_SAS_PRIORITY_UNCHANGED) {
+-              pKarg->IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              pKarg->Information.uFailureCode =
+-                  CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID;
+-              goto cim_set_raid_control_exit;
+-      }
+-
+-      if (pKarg->Information.bRebuildPriority !=
+-          CSMI_SAS_PRIORITY_AUTO &&
+-              pKarg->Information.bRebuildPriority !=
+-              CSMI_SAS_PRIORITY_UNCHANGED) {
+-              pKarg->IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              pKarg->Information.uFailureCode =
+-                  CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID;
+-              goto cim_set_raid_control_exit;
+-      }
+-
+-      if (pKarg->Information.bCacheRatioFlag ==
+-          CSMI_SAS_RAID_CACHE_RATIO_DISABLE) {
+-              pKarg->IoctlHeader.ReturnCode =
+-                  CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              pKarg->Information.uFailureCode =
+-                  CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID;
+-              goto cim_set_raid_control_exit;
+-      }
+-
+-      if( !strcmp(pKarg->Information.bClearConfiguration,
+-              CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE) ) {
+-              pKarg->IoctlHeader.ReturnCode =
+-                      CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              pKarg->Information.uFailureCode =
+-                      CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID;
+-              goto cim_set_raid_control_exit;
+-      }
+-
+-      pKarg->Information.bFailureDescription[0] = '\0';
+-
+- cim_set_raid_control_exit:
+-
+-      /*
+-       * Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, pKarg,
+-              sizeof(CSMI_SAS_RAID_CONTROL_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-              "Unable to write out csmi_sas_set_raid_control @ %p\n",
+-              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)pKarg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      free_pages((unsigned long)pKarg, memory_pages);
+-      return 0;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get Raid Element.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_raid_element(unsigned long arg)
+-{
+-      CSMI_SAS_RAID_ELEMENT_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_RAID_ELEMENT_BUFFER     karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      int                             iocnum;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmisas_get_raid_element struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-/* TODO - implement IOCTL here */
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
+-      dcsmisasprintk((": not implemented\n"));
+-
+-// csmisas_get_raid_element_exit:
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-                              sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to write out csmisas_get_raid_element @ %p\n",
+-                              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Set Raid Operation
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_set_raid_operation(unsigned long arg)
+-{
+-      CSMI_SAS_RAID_SET_OPERATION_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_RAID_SET_OPERATION_BUFFER       karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      int                             iocnum;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_set_raid_operation struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-/* TODO - implement IOCTL here */
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
+-      dcsmisasprintk((": not implemented\n"));
+-
+-// cim_set_raid_operation:
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-                              sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to write out csmi_set_raid_operation @ %p\n",
+-                              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-
+-}
+-
+-
+-/**
+- * Prototype Routine for the CSMI SAS Task Managment Config command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_task_managment(unsigned long arg)
+-{
+-      CSMI_SAS_SSP_TASK_IU_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_SSP_TASK_IU_BUFFER      karg;
+-      pSCSITaskMgmt_t                 pScsiTm;
+-      pSCSITaskMgmtReply_t            pScsiTmReply;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      MPT_SCSI_HOST                   *hd;
+-      MPT_FRAME_HDR                   *mf = NULL;
+-      MPIHeader_t                     *mpi_hdr;
+-      int                             iocnum;
+-      u8                              taskType;
+-      u8                              channel;
+-      u8                              id;
+-      u8                              queueTag;
+-      u32                             msgContext = 0;
+-      int                             i;
+-      u8                              found_qtag;
+-      struct sas_device_info          *sas_info;
+-      u16                             ioc_status;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_task_managment struct @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-
+-      sas_info = csmisas_get_device_component_by_os(ioc,
+-          karg.Parameters.bPathId, karg.Parameters.bTargetId);
+-      if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
+-              goto cim_get_task_managment_exit;
+-
+-      channel = sas_info->fw.channel;
+-      id = sas_info->fw.id;
+-      queueTag = (u8)karg.Parameters.uQueueTag & 0xFF;
+-      hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+-
+-      /* try to catch an error
+-       */
+-      if ((karg.Parameters.uFlags & CSMI_SAS_TASK_IU) &&
+-          (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE))
+-              goto cim_get_task_managment_exit;
+-
+-      if (karg.Parameters.uFlags & CSMI_SAS_TASK_IU) {
+-              switch (karg.Parameters.bTaskManagementFunction) {
+-
+-              case CSMI_SAS_SSP_ABORT_TASK:
+-                      taskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
+-                      break;
+-              case CSMI_SAS_SSP_ABORT_TASK_SET:
+-                      taskType = MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET;
+-                      break;
+-              case CSMI_SAS_SSP_CLEAR_TASK_SET:
+-                      taskType = MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET;
+-                      break;
+-              case CSMI_SAS_SSP_LOGICAL_UNIT_RESET:
+-                      taskType = MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET;
+-                      break;
+-              case CSMI_SAS_SSP_CLEAR_ACA:
+-              case CSMI_SAS_SSP_QUERY_TASK:
+-              default:
+-                      goto cim_get_task_managment_exit;
+-              }
+-      } else if (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE)
+-              taskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+-      else
+-              goto cim_get_task_managment_exit;
+-
+-      switch (karg.Parameters.uInformation) {
+-              case CSMI_SAS_SSP_TEST:
+-                      dcsmisasprintk(("TM request for test purposes\n"));
+-                      break;
+-              case CSMI_SAS_SSP_EXCEEDED:
+-                      dcsmisasprintk(("TM request due to timeout\n"));
+-                      break;
+-              case CSMI_SAS_SSP_DEMAND:
+-                      dcsmisasprintk(("TM request demanded by app\n"));
+-                      break;
+-              case CSMI_SAS_SSP_TRIGGER:
+-                      dcsmisasprintk(("TM request sent to trigger event\n"));
+-                      break;
+-      }
+-
+-      switch (taskType) {
+-
+-      case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
+-      /*
+-       * look up qtag in the ScsiLookup[] table
+-       */
+-              for (i = 0, found_qtag = 0; i < hd->ioc->req_depth; i++) {
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+-                      if ((hd->ScsiLookup[i]) &&
+-                          (hd->ScsiLookup[i]->tag == queueTag)) {
+-#else
+-                      if ((ioc->ScsiLookup[i]) &&
+-                          (ioc->ScsiLookup[i]->tag == queueTag)) {
+-#endif
+-                              mf = MPT_INDEX_2_MFPTR(hd->ioc, i);
+-                              msgContext =
+-                                  mf->u.frame.hwhdr.msgctxu.MsgContext;
+-                              found_qtag=1;
+-                              break;
+-                      }
+-              }
+-
+-              if(!found_qtag)
+-                      goto cim_get_task_managment_exit;
+-
+-      case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
+-      case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
+-      case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
+-      /* for now, this should work
+-       */
+-      case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
+-
+-              /* Single threading ....
+-               */
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+-              if (mptctl_set_tm_flags(hd) != 0) {
+-                      karg.IoctlHeader.ReturnCode =
+-                          CSMI_SAS_STATUS_FAILED;
+-                      goto cim_get_task_managment_exit;
+-              }
+-#endif
+-
+-              /* Send request
+-               */
+-              if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-                      dcsmisasprintk((": no msg frames!\n"));
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+-                      mptctl_free_tm_flags(ioc);
+-#endif
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto cim_get_task_managment_exit;
+-              }
+-
+-              mpi_hdr = (MPIHeader_t *) mf;
+-              pScsiTm = (pSCSITaskMgmt_t ) mf;
+-
+-              memset(pScsiTm,0,sizeof(SCSITaskMgmt_t));
+-              pScsiTm->TaskType = taskType;
+-              pScsiTm->Bus = channel;
+-              pScsiTm->TargetID = id;
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15))
+-              int_to_scsilun(karg.Parameters.bLun,
+-                  (struct scsi_lun *)pScsiTm->LUN);
+-#else
+-              pScsiTm->LUN[1] = karg.Parameters.bLun;
+-#endif
+-              pScsiTm->MsgContext = mpi_hdr->MsgContext;
+-              pScsiTm->TaskMsgContext = msgContext;
+-              pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+-
+-              if (csmisas_send_handshake_wait(ioc, mf,
+-                  karg.IoctlHeader.Timeout) != 0)  {
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto cim_get_task_managment_exit;
+-              }
+-
+-              if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+-
+-                      pScsiTmReply =
+-                          (pSCSITaskMgmtReply_t ) ioc->ioctl->ReplyFrame;
+-
+-                      ioc_status = le16_to_cpu(pScsiTmReply->IOCStatus)
+-                          & MPI_IOCSTATUS_MASK;
+-
+-                      memset(&karg.Status,0,
+-                          sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
+-
+-                      if(ioc_status == MPI_IOCSTATUS_SUCCESS) {
+-                              karg.IoctlHeader.ReturnCode =
+-                                  CSMI_SAS_STATUS_SUCCESS;
+-                              karg.Status.bSSPStatus =
+-                                  CSMI_SAS_SSP_STATUS_COMPLETED;
+-                      }else if(ioc_status == MPI_IOCSTATUS_INSUFFICIENT_RESOURCES) {
+-                              karg.IoctlHeader.ReturnCode =
+-                                  CSMI_SAS_STATUS_SUCCESS;
+-                              karg.Status.bSSPStatus =
+-                                  CSMI_SAS_SSP_STATUS_RETRY;
+-                      }else {
+-                              karg.IoctlHeader.ReturnCode =
+-                                  CSMI_SAS_STATUS_FAILED;
+-                              karg.Status.bSSPStatus =
+-                                  CSMI_SAS_SSP_STATUS_FATAL_ERROR;
+-                      }
+-              } else
+-                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-
+-              break;
+-
+-      default:
+-              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              break;
+-      }
+-
+-
+- cim_get_task_managment_exit:
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-                              sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to write out csmi_sas_task_managment @ %p\n",
+-                              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- *    map_sas_status_to_csmi - Conversion  for Connection Status
+- *    @mpi_sas_status: Sas status returned by the firmware
+- *
+- *    Returns converted connection status
+- *
+- **/
+-static u8
+-map_sas_status_to_csmi(u8 mpi_sas_status)
+-{
+-      u8  csmi_connect_status;
+-
+-      switch (mpi_sas_status) {
+-
+-      case MPI_SASSTATUS_SUCCESS:
+-              csmi_connect_status = CSMI_SAS_OPEN_ACCEPT;
+-              break;
+-
+-      case MPI_SASSTATUS_UTC_BAD_DEST:
+-              csmi_connect_status = CSMI_SAS_OPEN_REJECT_BAD_DESTINATION;
+-              break;
+-
+-      case MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED:
+-              csmi_connect_status = CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED;
+-              break;
+-
+-      case MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED:
+-              csmi_connect_status =
+-                  CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED;
+-              break;
+-
+-      case MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY:
+-              csmi_connect_status = CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY;
+-              break;
+-
+-      case MPI_SASSTATUS_UTC_WRONG_DESTINATION:
+-              csmi_connect_status = CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION;
+-              break;
+-
+-      case MPI_SASSTATUS_SDSF_NAK_RECEIVED:
+-              csmi_connect_status = CSMI_SAS_OPEN_REJECT_RETRY;
+-              break;
+-
+-      case MPI_SASSTATUS_SDSF_CONNECTION_FAILED:
+-              csmi_connect_status = CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED;
+-              break;
+-
+-      case MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT:
+-              csmi_connect_status =  CSMI_SAS_OPEN_REJECT_NO_DESTINATION;
+-              break;
+-
+-      case MPI_SASSTATUS_UNKNOWN_ERROR:
+-      case MPI_SASSTATUS_INVALID_FRAME:
+-      case MPI_SASSTATUS_UTC_BREAK_RECEIVED:
+-      case MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST:
+-      case MPI_SASSTATUS_SHORT_INFORMATION_UNIT:
+-      case MPI_SASSTATUS_LONG_INFORMATION_UNIT:
+-      case MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA:
+-      case MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR:
+-      case MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED:
+-      case MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH:
+-      case MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA:
+-      case MPI_SASSTATUS_DATA_OFFSET_ERROR:
+-              csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
+-              break;
+-
+-      default:
+-              csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
+-              break;
+-      }
+-
+-      return csmi_connect_status;
+-}
+-
+-/**
+- *                      csmisas_phy_reset
+- *    Issues a phy link reset or phy hard reset
+- *
+- *    @ioc - Pointer to MPT_ADAPTER structure
+- *    @PhyNum - phy number
+- *    @opcode - {MPI_SAS_OP_PHY_LINK_RESET,MPI_SAS_OP_PHY_HARD_RESET}
+- *
+- *    Returns: 0 for success, non-zero error
+- **/
+-static int
+-csmisas_phy_reset(MPT_ADAPTER *ioc, u8 PhyNum, u8 opcode)
+-{
+-      SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
+-      SasIoUnitControlReply_t         *sasIoUnitCntrReply;
+-      MPT_FRAME_HDR                   *mf = NULL;
+-      MPIHeader_t                     *mpi_hdr;
+-      u16                             ioc_status;
+-
+-      if ((opcode != MPI_SAS_OP_PHY_LINK_RESET) &&
+-          (opcode != MPI_SAS_OP_PHY_HARD_RESET))
+-          return -1;
+-
+-      /* Get a MF for this command.
+-       */
+-      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-              dcsmisasprintk((": no msg frames!\n"));
+-              return -1;
+-        }
+-
+-      mpi_hdr = (MPIHeader_t *) mf;
+-      sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+-      memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
+-      sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
+-      sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
+-      sasIoUnitCntrReq->Operation = opcode;
+-      sasIoUnitCntrReq->PhyNum = PhyNum;
+-
+-      if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0)
+-              return -1;
+-
+-      if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0)
+-              return -1;
+-
+-      /* process the completed Reply Message Frame */
+-      sasIoUnitCntrReply = (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame;
+-      ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus)
+-          & MPI_IOCSTATUS_MASK;
+-      if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
+-              printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
+-                  __FUNCTION__,
+-                  sasIoUnitCntrReply->IOCStatus,
+-                  sasIoUnitCntrReply->IOCLogInfo);
+-              return -1;
+-      }
+-      return 0;
+-}
+-
+-/** Prototype Routine for the CSMI SAS Phy Control command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_phy_control(unsigned long arg)
+-{
+-      CSMI_SAS_PHY_CONTROL_BUFFER __user *uarg = (void __user *) arg;
+-      IOCTL_HEADER                    ioctl_header;
+-      PCSMI_SAS_PHY_CONTROL_BUFFER    karg;
+-      SasIOUnitPage0_t                *sasIoUnitPg0=NULL;
+-      dma_addr_t                      sasIoUnitPg0_dma;
+-      int                             sasIoUnitPg0_data_sz=0;
+-      SasIOUnitPage1_t                *sasIoUnitPg1=NULL;
+-      dma_addr_t                      sasIoUnitPg1_dma;
+-      int                             sasIoUnitPg1_data_sz=0;
+-      ConfigExtendedPageHeader_t      hdr;
+-      CONFIGPARMS                     cfg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      int                             iocnum;
+-      int                             csmi_sas_phy_control_buffer_sz;
+-      int                             memory_pages;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in IOCTL_HEADER"
+-                  "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      csmi_sas_phy_control_buffer_sz = ioctl_header.Length;
+-      memory_pages = get_order(csmi_sas_phy_control_buffer_sz);
+-      karg = (PCSMI_SAS_PHY_CONTROL_BUFFER)__get_free_pages(
+-              GFP_KERNEL, memory_pages);
+-      if (!karg){
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to malloc SAS_PHY_CONTROL_BUFFER "
+-                      "csmi_sas_phy_control_buffer_sz=%d memory_pages=%d\n",
+-                      __FILE__, __LINE__, __FUNCTION__,
+-                      csmi_sas_phy_control_buffer_sz, memory_pages);
+-              return -ENOMEM;
+-      }
+-      memset(karg, 0, sizeof(*karg));
+-
+-      if (copy_from_user(karg, uarg, csmi_sas_phy_control_buffer_sz)) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_phy_control_buffer "
+-                  "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(ioctl_header.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      if (karg->bPhyIdentifier >= ioc->num_ports) {
+-              karg->IoctlHeader.ReturnCode =
+-                 CSMI_SAS_STATUS_INVALID_PARAMETER;
+-              goto cim_sas_phy_control_exit;
+-      }
+-
+-      /*
+-       *  Retreive SAS IOUNIT PAGE 0
+-       */
+-
+-      hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 0;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = 0;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              dcsmisasprintk((
+-                  ": FAILED: READ MPI_SASIOUNITPAGE0: HEADER\n"));
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sas_phy_control_exit;
+-      }
+-
+-      if (hdr.ExtPageLength == 0) {
+-              dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sas_phy_control_exit;
+-      }
+-
+-      sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
+-      sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
+-          sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
+-
+-      if (!sasIoUnitPg0) {
+-              dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sas_phy_control_exit;
+-      }
+-
+-      memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
+-      cfg.physAddr = sasIoUnitPg0_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              dcsmisasprintk((
+-                  ": FAILED: READ MPI_SASIOUNITPAGE0: CURRENT\n"));
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sas_phy_control_exit;
+-      }
+-
+-      /*
+-       *  Retreive SAS IOUNIT PAGE 1
+-       */
+-
+-      hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 1;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = 0;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              dcsmisasprintk((
+-                  ": FAILED: READ MPI_SASIOUNITPAGE1: HEADER\n"));
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sas_phy_control_exit;
+-      }
+-
+-      if (hdr.ExtPageLength == 0) {
+-              dcsmisasprintk((": hdr.ExtPageLength == 0\n"));
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sas_phy_control_exit;
+-      }
+-
+-      sasIoUnitPg1_data_sz = hdr.ExtPageLength * 4;
+-      sasIoUnitPg1 = (SasIOUnitPage1_t *) pci_alloc_consistent(ioc->pcidev,
+-          sasIoUnitPg1_data_sz, &sasIoUnitPg1_dma);
+-
+-      if (!sasIoUnitPg1) {
+-              dcsmisasprintk((": pci_alloc_consistent: FAILED\n"));
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sas_phy_control_exit;
+-      }
+-
+-      memset((u8 *)sasIoUnitPg1, 0, sasIoUnitPg1_data_sz);
+-      cfg.physAddr = sasIoUnitPg1_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              dcsmisasprintk((
+-                  ": FAILED:  READ MPI_SASIOUNITPAGE1: CURRENT\n"));
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-              goto cim_sas_phy_control_exit;
+-      }
+-
+-      switch (karg->uFunction) {
+-
+-      case CSMI_SAS_PC_LINK_RESET:
+-      case CSMI_SAS_PC_HARD_RESET:
+-      {
+-              u8 opcode = (karg->uFunction==CSMI_SAS_PC_LINK_RESET) ?
+-                  MPI_SAS_OP_PHY_LINK_RESET : MPI_SAS_OP_PHY_HARD_RESET;
+-
+-              if((karg->uLinkFlags & CSMI_SAS_PHY_ACTIVATE_CONTROL) &&
+-                  (karg->usLengthOfControl >= sizeof(CSMI_SAS_PHY_CONTROL)) &&
+-                  (karg->bNumberOfControls > 0)){
+-                      if(karg->Control[0].bRate ==
+-                         CSMI_SAS_LINK_RATE_1_5_GBPS) {
+-                              sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
+-                              MPI_SAS_IOUNIT1_MAX_RATE_1_5 |
+-                              MPI_SAS_IOUNIT1_MIN_RATE_1_5;
+-                      }
+-                      else if(karg->Control[0].bRate ==
+-                         CSMI_SAS_LINK_RATE_3_0_GBPS) {
+-                              sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
+-                              MPI_SAS_IOUNIT1_MAX_RATE_3_0 |
+-                              MPI_SAS_IOUNIT1_MIN_RATE_3_0;
+-                      }
+-                      sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags &=
+-                          ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
+-                      cfg.dir = 1;
+-                      cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
+-                      if (mpt_config(ioc, &cfg) != 0) {
+-                              dcsmisasprintk((
+-                          ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
+-                              karg->IoctlHeader.ReturnCode =
+-                                 CSMI_SAS_STATUS_FAILED;
+-                              goto cim_sas_phy_control_exit;
+-                      }
+-                      cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+-                      if (mpt_config(ioc, &cfg) != 0) {
+-                              dcsmisasprintk((
+-                       ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
+-                              karg->IoctlHeader.ReturnCode =
+-                                 CSMI_SAS_STATUS_FAILED;
+-                              goto cim_sas_phy_control_exit;
+-                      }
+-              }
+-              if (csmisas_phy_reset(ioc,
+-                  karg->bPhyIdentifier, opcode) != 0) {
+-                      dcsmisasprintk((
+-                          ": FAILED: csmisas_phy_reset\n"));
+-                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto cim_sas_phy_control_exit;
+-              }
+-              break;
+-
+-      }
+-      case CSMI_SAS_PC_PHY_DISABLE:
+-              if(karg->usLengthOfControl || karg->bNumberOfControls) {
+-                      karg->IoctlHeader.ReturnCode =
+-                          CSMI_SAS_STATUS_INVALID_PARAMETER;
+-                      break;
+-              }
+-              sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags |=
+-                  MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
+-              cfg.dir = 1;
+-              cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
+-              if (mpt_config(ioc, &cfg) != 0) {
+-                      dcsmisasprintk((
+-                          ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
+-                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto cim_sas_phy_control_exit;
+-              }
+-              cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+-              if (mpt_config(ioc, &cfg) != 0) {
+-                      dcsmisasprintk((
+-                          ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
+-                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto cim_sas_phy_control_exit;
+-              }
+-              if (csmisas_phy_reset(ioc,
+-                  karg->bPhyIdentifier, MPI_SAS_OP_PHY_HARD_RESET) != 0) {
+-                      dcsmisasprintk((
+-                          ": FAILED: csmisas_phy_reset\n"));
+-                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-                      goto cim_sas_phy_control_exit;
+-              }
+-              break;
+-
+-      case CSMI_SAS_PC_GET_PHY_SETTINGS:
+-              if(karg->usLengthOfControl || karg->bNumberOfControls) {
+-                      karg->IoctlHeader.ReturnCode =
+-                          CSMI_SAS_STATUS_INVALID_PARAMETER;
+-                      break;
+-              }
+-              if(csmi_sas_phy_control_buffer_sz <
+-                  offsetof(CSMI_SAS_PHY_CONTROL_BUFFER,Control) +
+-                  (4* sizeof(CSMI_SAS_PHY_CONTROL))) {
+-                      karg->IoctlHeader.ReturnCode =
+-                          CSMI_SAS_STATUS_INVALID_PARAMETER;
+-                      break;
+-              }
+-              karg->usLengthOfControl = sizeof(CSMI_SAS_PHY_CONTROL);
+-              karg->bNumberOfControls = 4;
+-              karg->Control[0].bType = CSMI_SAS_SAS;
+-              karg->Control[0].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
+-              karg->Control[1].bType = CSMI_SAS_SAS;
+-              karg->Control[1].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
+-              karg->Control[2].bType = CSMI_SAS_SATA;
+-              karg->Control[2].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
+-              karg->Control[3].bType = CSMI_SAS_SATA;
+-              karg->Control[3].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-              break;
+-      default:
+-              break;
+-      }
+-
+- cim_sas_phy_control_exit:
+-
+-      if (sasIoUnitPg0)
+-              pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
+-                  (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
+-
+-      if (sasIoUnitPg1)
+-              pci_free_consistent(ioc->pcidev, sasIoUnitPg1_data_sz,
+-                  (u8 *) sasIoUnitPg1, sasIoUnitPg1_dma);
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg,karg,csmi_sas_phy_control_buffer_sz)) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to write out csmi_sas_phy_control_buffer @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      free_pages((unsigned long)karg, memory_pages);
+-      return 0;
+-}
+-
+-/**
+- *    csmisas_get_manuf_pg_7 - Fetch Manufacturing config Page7.
+- * @ioc: Pointer to MPT_ADAPTER structure
+- * @mfgpage7_buffer: pointer to ManufacturingPage7_t that returns config
+- *                    page data
+- * @mfg_size - max size of buffer
+- *
+- *    Return: 0 for success
+- *    -ENOMEM if no memory available
+- *            -EPERM if not allowed due to ISR context
+- *            -EAGAIN if no msg frames currently available
+- *            -EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-csmisas_get_manuf_pg_7(MPT_ADAPTER *ioc, ManufacturingPage7_t *mfgpage7_buffer, int mfg_size)
+-{
+-      ConfigPageHeader_t hdr;
+-      CONFIGPARMS     cfg;
+-      ManufacturingPage7_t *mfgPage7 = NULL;
+-      dma_addr_t      mfgPage7_dma;
+-      int             data_sz = 0;
+-      int             rc;
+-
+-      /* Get Manufacturing Page 7 header */
+-      hdr.PageVersion = MPI_MANUFACTURING0_PAGEVERSION;
+-      hdr.PageLength = 0;
+-      hdr.PageNumber = 7;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
+-      cfg.cfghdr.hdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;
+-      cfg.pageAddr = 0;
+-      cfg.timeout = 0;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto csmisas_get_manuf_pg_7_exit;
+-
+-      if (hdr.PageLength == 0) {
+-              rc = -EFAULT;
+-              goto csmisas_get_manuf_pg_7_exit;
+-      }
+-
+-      data_sz = hdr.PageLength * 4;
+-      mfgPage7 = pci_alloc_consistent(ioc->pcidev, data_sz, &mfgPage7_dma);
+-      if (!mfgPage7) {
+-              rc = -ENOMEM;
+-              goto csmisas_get_manuf_pg_7_exit;
+-      }
+-
+-      memset((u8 *)mfgPage7, 0, data_sz);
+-      cfg.physAddr = mfgPage7_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto csmisas_get_manuf_pg_7_exit;
+-
+-      /* copy buffer back to user */
+-      memcpy(mfgpage7_buffer, mfgPage7, min(data_sz, mfg_size));
+-
+- csmisas_get_manuf_pg_7_exit:
+-
+-      if (mfgPage7)
+-              pci_free_consistent(ioc->pcidev, data_sz, (u8 *)mfgPage7,
+-                  mfgPage7_dma);
+-
+-      return rc;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get Connector info command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- **/
+-static int
+-csmisas_get_connector_info(unsigned long arg)
+-{
+-      CSMI_SAS_CONNECTOR_INFO_BUFFER __user *uarg = (void __user *) arg;
+-      CSMI_SAS_CONNECTOR_INFO_BUFFER   karg;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      ManufacturingPage7_t            *mfgPg7 = NULL;
+-      int                             mfgPg7_sz;
+-      int                             iocnum;
+-      int                             i;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&karg, uarg,
+-              sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                 "Unable to read in csmi_sas_connector_info_buffer"
+-                 " struct @ %p\n",
+-                 __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              return -ENODEV;
+-      }
+-
+-      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-
+-      /* `32` is the sizeof MPI_MANPAGE7_CONNECTOR_INFO */
+-      for (i = 0; i < 32; i++) {
+-              karg.Reference[i].uPinout = CSMI_SAS_CON_UNKNOWN;
+-              strcpy(karg.Reference[i].bConnector,"");
+-              karg.Reference[i].bLocation = CSMI_SAS_CON_UNKNOWN;
+-      }
+-
+-      mfgPg7_sz = offsetof(CONFIG_PAGE_MANUFACTURING_7,ConnectorInfo) +
+-          (ioc->num_ports * sizeof(MPI_MANPAGE7_CONNECTOR_INFO));
+-      mfgPg7 = kmalloc(mfgPg7_sz, GFP_KERNEL);
+-      if (!mfgPg7){
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to malloc @ %p\n",
+-                  __FILE__, __LINE__, __FUNCTION__, mfgPg7);
+-              return -EFAULT;
+-      }
+-      memset(mfgPg7, 0, mfgPg7_sz);
+-
+-      if (!csmisas_get_manuf_pg_7(ioc, mfgPg7, mfgPg7_sz)) {
+-              for (i = 0; i < ioc->num_ports; i++) {
+-                      karg.Reference[i].uPinout =
+-                          le32_to_cpu(mfgPg7->ConnectorInfo[i].Pinout);
+-                      /*endian conversion , this is u8 * 16 ?? */
+-                      strncpy(karg.Reference[i].bConnector,
+-                          mfgPg7->ConnectorInfo[i].Connector, 16);
+-                      karg.Reference[i].bLocation =
+-                          mfgPg7->ConnectorInfo[i].Location;
+-              }
+-      }
+-
+-      kfree(mfgPg7);
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg,
+-              sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-              "Unable to write out csmi_sas_connector_info_buffer @"
+-             "%p\n",
+-              __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return 0;
+-}
+-
+-/**
+- *                 csmisas_fill_location_data
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- **/
+-static int
+-csmisas_fill_location_data(MPT_ADAPTER *ioc, u8 bus, u8 id, u8 opcode,
+-      CSMI_SAS_LOCATION_IDENTIFIER * location_ident)
+-{
+-
+-      ConfigExtendedPageHeader_t      hdr;
+-      CONFIGPARMS                     cfg;
+-      int                             rc;
+-      SasDevicePage0_t                *sasDevicePg0=NULL;
+-      SasEnclosurePage0_t             *sasEnclosurePg0=NULL;
+-      dma_addr_t                      sasDevicePg0_dma,sasEnclosurePg0_dma;
+-      int                             sasDevicePg0_data_sz=0;
+-      int                             sasEnclosurePg0_data_sz=0;
+-      u64                             sas_address;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-      memset (location_ident, 0, sizeof(*location_ident));
+-
+-      /* SAS Device Page 0 */
+-      hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 0;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              rc=-1;
+-              goto fill_location_data_exit;
+-      }
+-
+-      if (hdr.ExtPageLength == 0) {
+-              rc=-1;
+-              goto fill_location_data_exit;
+-      }
+-
+-      sasDevicePg0_data_sz = hdr.ExtPageLength * 4;
+-      sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent(
+-          ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma);
+-      if (!sasDevicePg0) {
+-              rc=-1;
+-              goto fill_location_data_exit;
+-      }
+-
+-      memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz);
+-      cfg.physAddr = sasDevicePg0_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-      cfg.pageAddr = (bus << 8) + id
+-          + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+-                      MPI_SAS_DEVICE_PGAD_FORM_SHIFT);
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              rc=-1;
+-              goto fill_location_data_exit;
+-      }
+-
+-      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_ADDRESS_VALID;
+-      memcpy(&sas_address, &sasDevicePg0->SASAddress, sizeof(u64));
+-      sas_address = reverse_byte_order64(sas_address);
+-      memcpy(location_ident->bSASAddress, &sas_address, sizeof(u64));
+-
+-      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_LUN_VALID;
+-      memset(location_ident->bSASLun, 0, sizeof(location_ident->bSASLun));
+-
+-      /* SAS Enclosure Page 0 */
+-      hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 0;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              rc=0;
+-              goto fill_location_data_exit;
+-      }
+-
+-      if (hdr.ExtPageLength == 0) {
+-              rc=0;
+-              goto fill_location_data_exit;
+-      }
+-
+-      sasEnclosurePg0_data_sz = hdr.ExtPageLength * 4;
+-      sasEnclosurePg0 = (SasEnclosurePage0_t *) pci_alloc_consistent(
+-          ioc->pcidev, sasEnclosurePg0_data_sz, &sasEnclosurePg0_dma);
+-      if (!sasEnclosurePg0) {
+-              rc=0;
+-              goto fill_location_data_exit;
+-      }
+-      cfg.physAddr = sasEnclosurePg0_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-      cfg.pageAddr = sasDevicePg0->EnclosureHandle
+-          + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << MPI_SAS_ENCLOS_PGAD_FORM_SHIFT);
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0) {
+-              rc=0;
+-              goto fill_location_data_exit;
+-      }
+-
+-      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID;
+-      memcpy(&sas_address, &sasEnclosurePg0->EnclosureLogicalID, sizeof(u64));
+-      sas_address = reverse_byte_order64(sas_address);
+-      if (sas_address)
+-              memcpy(location_ident->bEnclosureIdentifier, &sas_address, sizeof(u64));
+-      else
+-              strcpy(location_ident->bEnclosureIdentifier,"Internal");
+-
+-// bBayPrefix - not supported
+-
+-// TODO - We need to look at sasEnclosurePg0-.Flags , to determine
+-//    whether SEP BUS/TargetID is valid.  Ifs its a SES device, then
+-//    issue internal inquiry to (bus/id) to gather the Enclosure name.
+-//    If the device is SMP, then issue SMP_MANUFACTURING to get enclosure name
+-//    If its direct attached, there is no enclosure name
+-      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID;
+-      strcpy(location_ident->bEnclosureName,"Not Supported");
+-
+-      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_LOCATION_STATE_VALID;
+-      location_ident->bLocationState = CSMI_SAS_LOCATE_UNKNOWN;
+-
+-      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID;
+-      location_ident->bBayIdentifier = le16_to_cpu(sasDevicePg0->Slot);
+-
+-
+-// TODO - illuminating LEDs,
+-// karg->bIdentify = CSMI_SAS_LOCATE_FORCE_OFF, CSMI_SAS_LOCATE_FORCE_ON
+-// We can enable/disable LEDs by SCSI Enclosure Processor MPI request message
+-// printk("Flags=0x%x\n",sasEnclosurePg0->Flags);
+-
+-/* check sasEnclosurePg0->Flags -
+- * to validate whether we need to send the SEPRequest
+- * bit:5 should be set
+- * bit:3-0 any bit should be set.  If zero, then SEPRequest will fail
+-*/
+-
+-/* MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR
+- * Look in mpi_init.h
+- * SEPRequest_t = structure
+- *
+- * SEPRequest_t->Action should be set to MPI_SEP_REQ_ACTION_WRITE_STATUS
+- *
+- * SEPRequest_t->Flags should be set to
+- * MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS, to pass along enclosure/slot ids
+- *
+- * SEPRequest_t->SlotStatus |= MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST - this
+- * will illuminate the LEDs
+- */
+-
+-fill_location_data_exit:
+-
+-      if (sasDevicePg0 != NULL)
+-              pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
+-                  sasDevicePg0, sasDevicePg0_dma);
+-
+-      if (sasEnclosurePg0 != NULL)
+-              pci_free_consistent(ioc->pcidev, sasEnclosurePg0_data_sz,
+-                  sasEnclosurePg0, sasEnclosurePg0_dma);
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      return rc;
+-}
+-
+-static int
+-csmisas_fill_location_data_raid(MPT_ADAPTER *ioc, PCSMI_SAS_GET_LOCATION_BUFFER karg, u8 VolumeBus,
+-      u8 volumeID)
+-{
+-      pRaidVolumePage0_t              pVolume0 = NULL;
+-      pRaidPhysDiskPage0_t            pPhysDisk0 = NULL;
+-      CONFIGPARMS                     cfg;
+-      ConfigPageHeader_t              header;
+-      u8                              physDiskNumMax;
+-      int                             volumepage0sz = 0, physdiskpage0sz = 0;
+-      dma_addr_t                      volume0_dma, physdisk0_dma;
+-      int                             csmi_sas_get_location_sz;
+-      int                             rc = 0, i, idx;
+-      int                             num_hotpares;
+-      u64                             totalMaxLBA, tmpTotalMaxLBA;
+-      IOCPage5_t                      *iocPage5 = NULL;
+-      u32                             device_info = 0;
+-      struct sas_device_info          *sas_info;
+-
+-      int                             sz;
+-
+-      csmi_sas_get_location_sz = karg->IoctlHeader.Length;
+-      physDiskNumMax = (csmi_sas_get_location_sz -
+-          offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location))
+-          / sizeof(CSMI_SAS_LOCATION_IDENTIFIER);
+-      karg->bNumberOfLocationIdentifiers=0;
+-
+-      /*
+-       * get RAID Volume Page 0
+-       */
+-
+-      header.PageVersion = 0;
+-      header.PageLength = 0;
+-      header.PageNumber = 0;
+-      header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+-      cfg.cfghdr.hdr = &header;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = (VolumeBus << 8) + volumeID;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              rc = -1;
+-              goto sas_fill_location_data_raid_exit;
+-      }
+-
+-      if (header.PageLength == 0) {
+-              rc = -1;
+-              goto sas_fill_location_data_raid_exit;
+-      }
+-
+-      volumepage0sz = header.PageLength * 4;
+-      pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
+-          &volume0_dma);
+-      if (!pVolume0) {
+-              rc = -1;
+-              goto sas_fill_location_data_raid_exit;
+-      }
+-
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-      cfg.physAddr = volume0_dma;
+-      if (mpt_config(ioc, &cfg) != 0){
+-              rc = -1;
+-              goto sas_fill_location_data_raid_exit;
+-      }
+-
+-      totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) |
+-          ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32;
+-
+-      /*
+-       * get RAID Physical Disk Page 0
+-       */
+-      header.PageVersion = 0;
+-      header.PageLength = 0;
+-      header.PageNumber = 0;
+-      header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+-      cfg.cfghdr.hdr = &header;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = 0;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;
+-      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              rc = -1;
+-              goto sas_fill_location_data_raid_exit;
+-      }
+-
+-      if (header.PageLength == 0) {
+-              rc = -1;
+-              goto sas_fill_location_data_raid_exit;
+-      }
+-
+-      physdiskpage0sz = header.PageLength * 4;
+-      pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
+-          &physdisk0_dma);
+-      if (!pPhysDisk0) {
+-              rc = -1;
+-              goto sas_fill_location_data_raid_exit;
+-      }
+-      cfg.physAddr = physdisk0_dma;
+-
+-      for (i=0; i < min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
+-
+-              /* obtain a refresh of pPhysDisk0 */
+-              cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-              cfg.pageAddr = pVolume0->PhysDisk[i].PhysDiskNum;
+-              if (mpt_config(ioc, &cfg) != 0){
+-                      rc = -1;
+-                      goto sas_fill_location_data_raid_exit;
+-              }
+-
+-              if((csmisas_fill_location_data(ioc, pPhysDisk0->PhysDiskBus,
+-                  pPhysDisk0->PhysDiskID, karg->bIdentify,
+-                  &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
+-                      karg->bNumberOfLocationIdentifiers++;
+-
+-              if (device_info)
+-                      continue;
+-              sas_info = csmisas_get_device_component_by_fw(ioc,
+-                  pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
+-              if (!sas_info || sas_info->is_cached)
+-                      continue;
+-              device_info = sas_info->device_info;
+-      }
+-
+-      if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS)
+-              goto sas_fill_location_data_raid_exit;
+-
+-      /*
+-       * hot spare support
+-       *
+-       */
+-
+-      num_hotpares = csmisas_get_number_hotspares(ioc);
+-
+-      if (num_hotpares) {
+-
+-              sz = offsetof(IOCPage5_t, HotSpare) +
+-                  num_hotpares * sizeof(IOC_5_HOT_SPARE);
+-              iocPage5 = kmalloc(sz, GFP_KERNEL);
+-
+-              if (!iocPage5)
+-                      goto sas_fill_location_data_raid_exit;
+-              memset(iocPage5, 0, sizeof(*iocPage5));
+-
+-              if (csmisas_get_ioc_pg5(ioc, iocPage5, sz) != 0)
+-                      goto sas_fill_location_data_raid_exit;
+-
+-              for(i = 0, idx = pVolume0->NumPhysDisks ; i < num_hotpares;
+-                  i++, idx++) {
+-
+-                      if (idx >= physDiskNumMax)
+-                              break;
+-
+-                      /* obtain a refresh of pPhysDisk0 */
+-                      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-                      cfg.pageAddr = iocPage5->HotSpare[i].PhysDiskNum;
+-                      if (mpt_config(ioc, &cfg) != 0)
+-                              goto sas_fill_location_data_raid_exit;
+-
+-                      /* Search the list for the matching SAS address. */
+-                      sas_info = csmisas_get_device_component_by_fw(ioc,
+-                          pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
+-
+-                      if (!sas_info || sas_info->is_cached)
+-                              continue;
+-
+-                      /* don't mix SSP hot spare
+-                       * in SATA volume
+-                       */
+-                      if (!csmisas_is_sata(pPhysDisk0) &&
+-                          (device_info &
+-                          MPI_SAS_DEVICE_INFO_SATA_DEVICE))
+-                              continue;
+-
+-                      /* don't mix SATA hot spare
+-                       * in SSP volume
+-                       */
+-                      if (csmisas_is_sata(pPhysDisk0) &&
+-                          (device_info &
+-                          MPI_SAS_DEVICE_INFO_SSP_TARGET))
+-                              continue;
+-
+-                      /* capacity check for IM volumes*/
+-                      if ((pVolume0->VolumeType ==
+-                          MPI_RAID_VOL_TYPE_IM) &&
+-                          (totalMaxLBA +
+-                          (64*2*1024) /* metadata = 64MB*/ >
+-                          le32_to_cpu(pPhysDisk0->MaxLBA)))
+-                              continue;
+-
+-                      tmpTotalMaxLBA = totalMaxLBA;
+-                      do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
+-                      /* capacity check for IME volumes*/
+-                      if ((pVolume0->VolumeType ==
+-                              MPI_RAID_VOL_TYPE_IME) &&
+-                          ((tmpTotalMaxLBA * 2) +
+-                           (64*2*1024 ) /*metadata = 64MB*/ >
+-                          le32_to_cpu(pPhysDisk0->MaxLBA)))
+-                              continue;
+-
+-                      if((csmisas_fill_location_data(ioc,
+-                          pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID,
+-                          karg->bIdentify,
+-                          &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
+-                              karg->bNumberOfLocationIdentifiers++;
+-              }
+-      }
+-
+-
+- sas_fill_location_data_raid_exit:
+-
+-      kfree(iocPage5);
+-
+-      if (pVolume0)
+-              pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
+-                  volume0_dma);
+-
+-      if(pPhysDisk0)
+-              pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
+-                  physdisk0_dma);
+-
+-      return rc;
+-}
+-
+-/**
+- * Prototype Routine for the CSMI SAS Get location command.
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- *            -ENODEV if no such device/adapter
+- */
+-static int
+-csmisas_get_location(unsigned long arg)
+-{
+-      CSMI_SAS_GET_LOCATION_BUFFER __user *uarg = (void __user *) arg;
+-      PCSMI_SAS_GET_LOCATION_BUFFER   karg;
+-      IOCTL_HEADER                    ioctl_header;
+-      MPT_ADAPTER                     *ioc = NULL;
+-      int                             iocnum,i;
+-      int                             csmi_sas_get_location_sz;
+-      int                             memory_pages;
+-      struct sas_device_info          *sas_info;
+-
+-      dcsmisasprintk(("%s enter.\n",__FUNCTION__));
+-
+-      if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in IOCTL_HEADER"
+-                  "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
+-              return -EFAULT;
+-      }
+-
+-      csmi_sas_get_location_sz = ioctl_header.Length;
+-      memory_pages = get_order(csmi_sas_get_location_sz);
+-      karg = (PCSMI_SAS_GET_LOCATION_BUFFER)__get_free_pages(
+-              GFP_KERNEL, memory_pages);
+-      if (!karg){
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                      "Unable to malloc GET_LOCATION_BUFFER "
+-                      "csmi_sas_get_location_sz=%d memory_pages=%d\n",
+-                      __FILE__, __LINE__, __FUNCTION__,
+-                      csmi_sas_get_location_sz, memory_pages);
+-              return -ENOMEM;
+-      }
+-      memset(karg, 0, sizeof(*karg));
+-
+-      if (copy_from_user(karg, uarg, csmi_sas_get_location_sz)) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to read in csmi_sas_phy_control_buffer "
+-                  "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
+-          &ioc)) < 0) || (ioc == NULL)) {
+-              dcsmisasprintk((KERN_ERR
+-              "%s::%s() @%d - ioc%d not found!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      if (!csmisas_is_this_sas_cntr(ioc)) {
+-              dcsmisasprintk((KERN_ERR
+-                  "%s::%s() @%d - ioc%d not SAS controller!\n",
+-                  __FILE__, __FUNCTION__, __LINE__, iocnum));
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -ENODEV;
+-      }
+-
+-      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
+-      if(karg->bLengthOfLocationIdentifier !=
+-          sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
+-              goto cim_sas_get_location_exit;
+-
+-      sas_info = csmisas_get_device_component_by_os(ioc, karg->bPathId,
+-          karg->bTargetId);
+-      if (!sas_info)
+-              goto cim_sas_get_location_exit;
+-
+-      /* RAID SUPPORT */
+-      if (ioc->raid_data.pIocPg2 && sas_info->is_logical_volume) {
+-              for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){
+-                      if (sas_info->fw.id ==
+-                          ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID &&
+-                          sas_info->fw.channel ==
+-                          ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus) {
+-                              if(csmisas_fill_location_data_raid(ioc, karg,
+-                                  ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus,
+-                                  ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) == 0)
+-                                      karg->IoctlHeader.ReturnCode =
+-                                          CSMI_SAS_STATUS_SUCCESS;
+-                              else
+-                                      karg->IoctlHeader.ReturnCode =
+-                                          CSMI_SAS_STATUS_FAILED;
+-                              goto cim_sas_get_location_exit;
+-                      }
+-              }
+-      }
+-
+-      /* NON-RAID SUPPORT */
+-      if (sas_info->is_cached || sas_info->is_logical_volume)
+-              goto cim_sas_get_location_exit;
+-
+-      /* make sure there's enough room to populate the Location[] struct */
+-      if ((csmi_sas_get_location_sz -
+-          offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) <
+-          sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
+-              goto cim_sas_get_location_exit;
+-
+-      karg->bNumberOfLocationIdentifiers=1;
+-      karg->Location[0].bLocationFlags=0;
+-      if((csmisas_fill_location_data(ioc, sas_info->fw.channel,
+-          sas_info->fw.id, karg->bIdentify, &karg->Location[0])) == 0)
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
+-      else
+-              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
+-
+- cim_sas_get_location_exit:
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, karg, csmi_sas_get_location_sz)) {
+-              printk(KERN_ERR "%s@%d::%s() - "
+-                  "Unable to write out csmi_sas_get_location_buffer "
+-                  "@ %p\n",__FILE__, __LINE__, __FUNCTION__, uarg);
+-              free_pages((unsigned long)karg, memory_pages);
+-              return -EFAULT;
+-      }
+-
+-      dcsmisasprintk(("%s exit.\n",__FUNCTION__));
+-      free_pages((unsigned long)karg, memory_pages);
+-      return 0;
+-}
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.h linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.h   2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.h  1970-01-01 01:00:00.000000000 +0100
+@@ -1,1854 +0,0 @@
+-/**************************************************************************
+-
+-Module Name:
+-
+-   CSMISAS.H
+-
+-
+-Abstract:
+-
+-   This file contains constants and data structure definitions used by drivers
+-   that support the Common Storage Management Interface specification for
+-   SAS or SATA in either the Windows or Linux.
+-
+-   This should be considered as a reference implementation only.  Changes may
+-   be necessary to accommodate a specific build environment or target OS.
+-
+-Revision History:
+-
+-   001  SEF   8/12/03  Initial release.
+-   002  SEF   8/20/03  Cleanup to match documentation.
+-   003  SEF   9/12/03  Additional cleanup, created combined header
+-   004  SEF   9/23/03  Changed base types to match linux defaults
+-                       Added RAID signature
+-                       Added bControllerFlags to CSMI_SAS_CNTLR_CONFIG
+-                       Changed CSMI_SAS_BEGIN_PACK to 8 for common structures
+-                       Fixed other typos identified in first compilation test
+-   005  SEF  10/03/03  Additions to match first version of CSMI document
+-   006  SEF  10/14/03  Fixed typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER
+-                       Added defines for bConnectionRate
+-   007  SEF  10/15/03  Added Firmware Download Control Code and support
+-                       Added CSMI revision support
+-   008  SEF  10/30/03  No functional change, just updated version to track
+-                       spec changes
+-   009  SEF  12/09/03  No functional change, just updated version to track
+-                       spec changes
+-   010  SEF   3/11/04  Fixed typedef struct CSMI_SAS_RAID_DRIVES to include the
+-                       bFirmware member that is defined in the spec, but
+-                       was missing in this file,
+-                       added CC_CSMI_SAS_TASK_MANAGEMENT
+-   011  SEF   4/02/04  No functional change, added comment line before
+-                       CC_CSMI_SAS_TASK_MANAGEMENT
+-   012  SEF   4/16/04  Added IOControllerNumber to linux header,
+-                       Modified linux control codes to have upper word of
+-                       0xCC77.... to indicate CSMI version 77
+-                       Added bSignalClass to CC_CSMI_SET_PHY_INFO
+-                       Added CC_CSMI_SAS_PHY_CONTROL support
+-   013  SEF   5/14/04  Added CC_CSMI_SAS_GET_CONNECTOR_INFO support
+-   014  SEF   5/24/04  No functional change, just updated version to track spec
+-                       changes
+-   015  SEF   6/16/04  changed bPinout to uPinout to reflect proper size,
+-                       changed width of bLocation defines to reflect size
+-   016  SEF   6/17/04  changed bLengthOfControls in CSMI_SAS_PHY_CONTROL
+-                       to be proper size
+-   017  SEF   9/17/04  added CSMI_SAS_SATA_PORT_SELECTOR,
+-                       CSMI_SAS_LINK_VIRTUAL, CSMI_SAS_CON_NOT_PRESENT, and
+-                       CSMI_SAS_CON_NOT_CONNECTED
+-   018  SEF   9/20/04  added CSMI_SAS_PHY_USER_PATTERN,
+-                       changed definition of CSMI_SAS_PHY_FIXED_PATTERN to not
+-                       conflict with activate definition
+-   019  SEF  12/06/04  added CSMI_SAS_GET_LOCATION
+-                       added bSSPStatus to CSMI_SAS_SSP_PASSTHRU_STATUS
+-                       structure
+-   020  SEF   5/25/05  added CSMI_SAS_PHY_VIRTUAL_SMP, and changes to
+-                       CSMI_SAS_GET_LOCATION
+-   021  SEF  11/03/05  added new RAID creation functionality
+-   022  SEF   2/01/06  corrected typo bNegotitiatedLInkRate
+-                       Added two more RAID_TYPES, 7 and 8
+-   023  SEF   4/04/06  added CSMI_RAID_TYPE_1E
+-                       changed structures that contained surface scan
+-                       to priority approach rather than time, causes
+-                       0.89 to incompatible with 0.87, so a version
+-                       check is necessary when interpreting the
+-                       raid structures
+-                       Added netware section
+-   024 DRG    5/22/06  Added uFailureCode to CSMI_SAS_RAID_CONFIG and
+-                       CSMI_SAS_RAID_FEATURES
+-                       Changed __u64 fields to high and low __u32 fields in
+-                       order to avoid backward compatibility issues with
+-                       packing and alignment.
+-                       Fixed alignment problem in CSMI_SAS_RAID_DRIVES.
+-                       Added CSMI_SAS_CNTLR_SMART_ARRAY to uControllerFlags
+-                       Reassigned the value of CSMI_SAS_CNTLR_RAID_CFG_SUPPORT
+-                       to avoid a conflict.
+-
+-**************************************************************************/
+-
+-#ifndef _CSMI_SAS_H_
+-#define _CSMI_SAS_H_
+-
+-// CSMI Specification Revision, the intent is that all versions of the
+-// specification will be backward compatible after the 1.00 release.
+-// Major revision number, corresponds to xxxx. of CSMI specification
+-// Minor revision number, corresponds to .xxxx of CSMI specification
+-#define CSMI_MAJOR_REVISION   0
+-#define CSMI_MINOR_REVISION   90
+-
+-/*************************************************************************/
+-/* PATCHES FOR TYPOS                                                     */
+-/*************************************************************************/
+-
+-#define bNegotitiatedLInkRate bNegotiatedLinkRate
+-
+-/*************************************************************************/
+-/* TARGET OS LINUX SPECIFIC CODE                                         */
+-/*************************************************************************/
+-
+-// EDM #ifdef _linux
+-#ifdef __KERNEL__
+-
+-// Linux base types
+-
+-#include <linux/types.h>
+-
+-#define __i8    char
+-
+-// pack definition
+-
+-// EDM #define CSMI_SAS_BEGIN_PACK(x)    pack(x)
+-// EDM #define CSMI_SAS_END_PACK         pack()
+-
+-// IOCTL Control Codes
+-// (IoctlHeader.ControlCode)
+-
+-// Control Codes prior to 0.77
+-
+-// Control Codes requiring CSMI_ALL_SIGNATURE
+-
+-// #define CC_CSMI_SAS_GET_DRIVER_INFO    0x12345678
+-// #define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x23456781
+-// #define CC_CSMI_SAS_GET_CNTLR_STATUS   0x34567812
+-// #define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x92345678
+-
+-// Control Codes requiring CSMI_RAID_SIGNATURE
+-
+-// #define CC_CSMI_SAS_GET_RAID_INFO      0x45678123
+-// #define CC_CSMI_SAS_GET_RAID_CONFIG    0x56781234
+-
+-// Control Codes requiring CSMI_SAS_SIGNATURE
+-
+-// #define CC_CSMI_SAS_GET_PHY_INFO       0x67812345
+-// #define CC_CSMI_SAS_SET_PHY_INFO       0x78123456
+-// #define CC_CSMI_SAS_GET_LINK_ERRORS    0x81234567
+-// #define CC_CSMI_SAS_SMP_PASSTHRU       0xA1234567
+-// #define CC_CSMI_SAS_SSP_PASSTHRU       0xB1234567
+-// #define CC_CSMI_SAS_STP_PASSTHRU       0xC1234567
+-// #define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xD1234567
+-// #define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xE1234567
+-// #define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xF1234567
+-// #define CC_CSMI_SAS_TASK_MANAGEMENT    0xA2345678
+-
+-// Control Codes for 0.77 and later
+-
+-// Control Codes requiring CSMI_ALL_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_DRIVER_INFO    0xCC770001
+-#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0xCC770002
+-#define CC_CSMI_SAS_GET_CNTLR_STATUS   0xCC770003
+-#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0xCC770004
+-
+-// Control Codes requiring CSMI_RAID_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_RAID_INFO      0xCC77000A
+-#define CC_CSMI_SAS_GET_RAID_CONFIG    0xCC77000B
+-#define CC_CSMI_SAS_GET_RAID_FEATURES  0xCC77000C
+-#define CC_CSMI_SAS_SET_RAID_CONTROL   0xCC77000D
+-#define CC_CSMI_SAS_GET_RAID_ELEMENT   0xCC77000E
+-#define CC_CSMI_SAS_SET_RAID_OPERATION 0xCC77000F
+-
+-// Control Codes requiring CSMI_SAS_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_PHY_INFO       0xCC770014
+-#define CC_CSMI_SAS_SET_PHY_INFO       0xCC770015
+-#define CC_CSMI_SAS_GET_LINK_ERRORS    0xCC770016
+-#define CC_CSMI_SAS_SMP_PASSTHRU       0xCC770017
+-#define CC_CSMI_SAS_SSP_PASSTHRU       0xCC770018
+-#define CC_CSMI_SAS_STP_PASSTHRU       0xCC770019
+-#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xCC770020
+-#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xCC770021
+-#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xCC770022
+-#define CC_CSMI_SAS_TASK_MANAGEMENT    0xCC770023
+-#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0xCC770024
+-#define CC_CSMI_SAS_GET_LOCATION       0xCC770025
+-
+-
+-// Control Codes requiring CSMI_PHY_SIGNATURE
+-
+-#define CC_CSMI_SAS_PHY_CONTROL        0xCC77003C
+-
+-// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
+-#pragma pack(8)
+-
+-// IOCTL_HEADER
+-typedef struct _IOCTL_HEADER {
+-    __u32 IOControllerNumber;
+-    __u32 Length;
+-    __u32 ReturnCode;
+-    __u32 Timeout;
+-    __u16 Direction;
+-} IOCTL_HEADER,
+-  *PIOCTL_HEADER;
+-
+-// EDM #pragma CSMI_SAS_END_PACK
+-#pragma pack()
+-
+-#endif
+-
+-/*************************************************************************/
+-/* TARGET OS WINDOWS SPECIFIC CODE                                       */
+-/*************************************************************************/
+-
+-#ifdef _WIN32
+-
+-// windows IOCTL definitions
+-
+-#ifndef _NTDDSCSIH_
+-#include <ntddscsi.h>
+-#endif
+-
+-// pack definition
+-
+-#if defined _MSC_VER
+-   #define CSMI_SAS_BEGIN_PACK(x)    pack(push,x)
+-   #define CSMI_SAS_END_PACK         pack(pop)
+-#elif defined __BORLANDC__
+-   #define CSMI_SAS_BEGIN_PACK(x)    option -a##x
+-   #define CSMI_SAS_END_PACK         option -a.
+-#else
+-   #error "CSMISAS.H - Must externally define a pack compiler designator."
+-#endif
+-
+-// base types
+-
+-#define __u8    unsigned char
+-#define __u16   unsigned short
+-#define __u32   unsigned long
+-#define __u64   unsigned __int64
+-
+-#define __i8    char
+-
+-// IOCTL Control Codes
+-// (IoctlHeader.ControlCode)
+-
+-// Control Codes requiring CSMI_ALL_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_DRIVER_INFO    1
+-#define CC_CSMI_SAS_GET_CNTLR_CONFIG   2
+-#define CC_CSMI_SAS_GET_CNTLR_STATUS   3
+-#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  4
+-
+-// Control Codes requiring CSMI_RAID_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_RAID_INFO      10
+-#define CC_CSMI_SAS_GET_RAID_CONFIG    11
+-#define CC_CSMI_SAS_GET_RAID_FEATURES  12
+-#define CC_CSMI_SAS_SET_RAID_CONTROL   13
+-#define CC_CSMI_SAS_GET_RAID_ELEMENT   14
+-#define CC_CSMI_SAS_SET_RAID_OPERATION 15
+-
+-// Control Codes requiring CSMI_SAS_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_PHY_INFO       20
+-#define CC_CSMI_SAS_SET_PHY_INFO       21
+-#define CC_CSMI_SAS_GET_LINK_ERRORS    22
+-#define CC_CSMI_SAS_SMP_PASSTHRU       23
+-#define CC_CSMI_SAS_SSP_PASSTHRU       24
+-#define CC_CSMI_SAS_STP_PASSTHRU       25
+-#define CC_CSMI_SAS_GET_SATA_SIGNATURE 26
+-#define CC_CSMI_SAS_GET_SCSI_ADDRESS   27
+-#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 28
+-#define CC_CSMI_SAS_TASK_MANAGEMENT    29
+-#define CC_CSMI_SAS_GET_CONNECTOR_INFO 30
+-#define CC_CSMI_SAS_GET_LOCATION       31
+-
+-// Control Codes requiring CSMI_PHY_SIGNATURE
+-
+-#define CC_CSMI_SAS_PHY_CONTROL        60
+-
+-#define IOCTL_HEADER SRB_IO_CONTROL
+-#define PIOCTL_HEADER PSRB_IO_CONTROL
+-
+-#endif
+-
+-/*************************************************************************/
+-/* TARGET OS NETWARE SPECIFIC CODE                                       */
+-/*************************************************************************/
+-
+-#ifdef _NETWARE
+-
+-// NetWare IOCTL definitions
+-
+-#define CSMI_SAS_BEGIN_PACK(x)    pack(x)
+-#define CSMI_SAS_END_PACK         pack()
+-
+-#ifndef LONG
+-typedef unsigned long LONG;
+-#endif
+-
+-#ifndef WORD
+-typedef unsigned short WORD;
+-#endif
+-
+-#ifndef BYTE
+-typedef unsigned char BYTE;
+-#endif
+-
+-/* Need to have these definitions for Netware */
+-#define __u8    unsigned char
+-#define __u16   unsigned short
+-#define __u32   unsigned long
+-#define __u64   unsigned __int64
+-
+-#define __i8    char
+-
+-
+-// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
+-#pragma pack(8)
+-
+-// IOCTL_HEADER
+-typedef struct _IOCTL_HEADER {
+-    __u32 Length;
+-    __u32 ReturnCode;
+-} IOCTL_HEADER,
+-  *PIOCTL_HEADER;
+-
+-// EDM #pragma CSMI_SAS_END_PACK
+-#pragma pack()
+-
+-// IOCTL Control Codes
+-// (IoctlHeader.ControlCode)
+-
+-// Control Codes requiring CSMI_ALL_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_DRIVER_INFO    0x01FF0001
+-#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x01FF0002
+-#define CC_CSMI_SAS_GET_CNTLR_STATUS   0x01FF0003
+-#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x01FF0004
+-
+-// Control Codes requiring CSMI_RAID_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_RAID_INFO      0x01FF000A
+-#define CC_CSMI_SAS_GET_RAID_CONFIG    0x01FF000B
+-#define CC_CSMI_SAS_GET_RAID_FEATURES  0x01FF000C
+-#define CC_CSMI_SAS_SET_RAID_CONTROL   0x01FF000D
+-#define CC_CSMI_SAS_GET_RAID_ELEMENT   0x01FF000E
+-#define CC_CSMI_SAS_SET_RAID_OPERATION 0x01FF000F
+-
+-// Control Codes requiring CSMI_SAS_SIGNATURE
+-
+-#define CC_CSMI_SAS_GET_PHY_INFO       0x01FF0014
+-#define CC_CSMI_SAS_SET_PHY_INFO       0x01FF0015
+-#define CC_CSMI_SAS_GET_LINK_ERRORS    0x01FF0016
+-#define CC_CSMI_SAS_SMP_PASSTHRU       0x01FF0017
+-#define CC_CSMI_SAS_SSP_PASSTHRU       0x01FF0018
+-#define CC_CSMI_SAS_STP_PASSTHRU       0x01FF0019
+-#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0x01FF001A
+-#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0x01FF001B
+-#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0x01FF001C
+-#define CC_CSMI_SAS_TASK_MANAGEMENT    0x01FF001D
+-#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0x01FF001E
+-#define CC_CSMI_SAS_GET_LOCATION       0x01FF001F
+-
+-// Control Codes requiring CSMI_PHY_SIGNATURE
+-
+-#define CC_CSMI_SAS_PHY_CONTROL        60
+-
+-#endif
+-
+-/*************************************************************************/
+-/* TARGET OS NOT DEFINED ERROR                                           */
+-/*************************************************************************/
+-
+-// EDM
+-//#if (!_WIN32 && !_linux && !_NETWARE)
+-//   #error "Unknown target OS."
+-//#endif
+-
+-/*************************************************************************/
+-/* OS INDEPENDENT CODE                                                   */
+-/*************************************************************************/
+-
+-/* * * * * * * * * * Class Independent IOCTL Constants * * * * * * * * * */
+-
+-// Return codes for all IOCTL's regardless of class
+-// (IoctlHeader.ReturnCode)
+-
+-#define CSMI_SAS_STATUS_SUCCESS              0
+-#define CSMI_SAS_STATUS_FAILED               1
+-#define CSMI_SAS_STATUS_BAD_CNTL_CODE        2
+-#define CSMI_SAS_STATUS_INVALID_PARAMETER    3
+-#define CSMI_SAS_STATUS_WRITE_ATTEMPTED      4
+-
+-// Signature value
+-// (IoctlHeader.Signature)
+-
+-#define CSMI_ALL_SIGNATURE    "CSMIALL"
+-
+-// Timeout value default of 60 seconds
+-// (IoctlHeader.Timeout)
+-
+-#define CSMI_ALL_TIMEOUT      60
+-
+-//  Direction values for data flow on this IOCTL
+-// (IoctlHeader.Direction, Linux only)
+-#define CSMI_SAS_DATA_READ    0
+-#define CSMI_SAS_DATA_WRITE   1
+-
+-// I/O Bus Types
+-// ISA and EISA bus types are not supported
+-// (bIoBusType)
+-
+-#define CSMI_SAS_BUS_TYPE_PCI       3
+-#define CSMI_SAS_BUS_TYPE_PCMCIA    4
+-
+-// Controller Status
+-// (uStatus)
+-
+-#define CSMI_SAS_CNTLR_STATUS_GOOD     1
+-#define CSMI_SAS_CNTLR_STATUS_FAILED   2
+-#define CSMI_SAS_CNTLR_STATUS_OFFLINE  3
+-#define CSMI_SAS_CNTLR_STATUS_POWEROFF 4
+-
+-// Offline Status Reason
+-// (uOfflineReason)
+-
+-#define CSMI_SAS_OFFLINE_REASON_NO_REASON             0
+-#define CSMI_SAS_OFFLINE_REASON_INITIALIZING          1
+-#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_DEGRADED 2
+-#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_FAILURE  3
+-
+-// Controller Class
+-// (bControllerClass)
+-
+-#define CSMI_SAS_CNTLR_CLASS_HBA    5
+-
+-// Controller Flag bits
+-// (uControllerFlags)
+-
+-#define CSMI_SAS_CNTLR_SAS_HBA          0x00000001
+-#define CSMI_SAS_CNTLR_SAS_RAID         0x00000002
+-#define CSMI_SAS_CNTLR_SATA_HBA         0x00000004
+-#define CSMI_SAS_CNTLR_SATA_RAID        0x00000008
+-#define CSMI_SAS_CNTLR_SMART_ARRAY      0x00000010
+-
+-// for firmware download
+-#define CSMI_SAS_CNTLR_FWD_SUPPORT      0x00010000
+-#define CSMI_SAS_CNTLR_FWD_ONLINE       0x00020000
+-#define CSMI_SAS_CNTLR_FWD_SRESET       0x00040000
+-#define CSMI_SAS_CNTLR_FWD_HRESET       0x00080000
+-#define CSMI_SAS_CNTLR_FWD_RROM         0x00100000
+-
+-// for RAID configuration supported
+-#define CSMI_SAS_CNTLR_RAID_CFG_SUPPORT 0x01000000
+-
+-// Download Flag bits
+-// (uDownloadFlags)
+-#define CSMI_SAS_FWD_VALIDATE       0x00000001
+-#define CSMI_SAS_FWD_SOFT_RESET     0x00000002
+-#define CSMI_SAS_FWD_HARD_RESET     0x00000004
+-
+-// Firmware Download Status
+-// (usStatus)
+-#define CSMI_SAS_FWD_SUCCESS        0
+-#define CSMI_SAS_FWD_FAILED         1
+-#define CSMI_SAS_FWD_USING_RROM     2
+-#define CSMI_SAS_FWD_REJECT         3
+-#define CSMI_SAS_FWD_DOWNREV        4
+-
+-// Firmware Download Severity
+-// (usSeverity>
+-#define CSMI_SAS_FWD_INFORMATION    0
+-#define CSMI_SAS_FWD_WARNING        1
+-#define CSMI_SAS_FWD_ERROR          2
+-#define CSMI_SAS_FWD_FATAL          3
+-
+-/* * * * * * * * * * SAS RAID Class IOCTL Constants  * * * * * * * * */
+-
+-// Return codes for the RAID IOCTL's regardless of class
+-// (IoctlHeader.ReturnCode)
+-
+-#define CSMI_SAS_RAID_SET_OUT_OF_RANGE       1000
+-#define CSMI_SAS_RAID_SET_BUFFER_TOO_SMALL   1001
+-#define CSMI_SAS_RAID_SET_DATA_CHANGED       1002
+-
+-// Signature value
+-// (IoctlHeader.Signature)
+-
+-#define CSMI_RAID_SIGNATURE    "CSMIARY"
+-
+-// Timeout value default of 60 seconds
+-// (IoctlHeader.Timeout)
+-
+-#define CSMI_RAID_TIMEOUT      60
+-
+-// RAID Types
+-// (bRaidType)
+-#define CSMI_SAS_RAID_TYPE_NONE     0
+-#define CSMI_SAS_RAID_TYPE_0        1
+-#define CSMI_SAS_RAID_TYPE_1        2
+-#define CSMI_SAS_RAID_TYPE_10       3
+-#define CSMI_SAS_RAID_TYPE_5        4
+-#define CSMI_SAS_RAID_TYPE_15       5
+-#define CSMI_SAS_RAID_TYPE_6        6
+-#define CSMI_SAS_RAID_TYPE_50       7
+-#define CSMI_SAS_RAID_TYPE_VOLUME   8
+-#define CSMI_SAS_RAID_TYPE_1E       9
+-#define CSMI_SAS_RAID_TYPE_OTHER    255
+-// the last value 255 was already defined for other
+-// so end is defined as 254
+-#define CSMI_SAS_RAID_TYPE_END      254
+-
+-// RAID Status
+-// (bStatus)
+-#define CSMI_SAS_RAID_SET_STATUS_OK             0
+-#define CSMI_SAS_RAID_SET_STATUS_DEGRADED       1
+-#define CSMI_SAS_RAID_SET_STATUS_REBUILDING     2
+-#define CSMI_SAS_RAID_SET_STATUS_FAILED         3
+-#define CSMI_SAS_RAID_SET_STATUS_OFFLINE        4
+-#define CSMI_SAS_RAID_SET_STATUS_TRANSFORMING   5
+-#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_REBUILD         6
+-#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_TRANSFORMATION  7
+-
+-// RAID Drive Count
+-// (bDriveCount, 0xF1 to 0xFF are reserved)
+-#define CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG   0xF1
+-#define CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED 0xF2
+-
+-// RAID Data Type
+-// (bDataType)
+-#define CSMI_SAS_RAID_DATA_DRIVES           0
+-#define CSMI_SAS_RAID_DATA_DEVICE_ID        1
+-#define CSMI_SAS_RAID_DATA_ADDITIONAL_DATA  2
+-
+-// RAID Drive Status
+-// (bDriveStatus)
+-#define CSMI_SAS_DRIVE_STATUS_OK          0
+-#define CSMI_SAS_DRIVE_STATUS_REBUILDING  1
+-#define CSMI_SAS_DRIVE_STATUS_FAILED      2
+-#define CSMI_SAS_DRIVE_STATUS_DEGRADED    3
+-#define CSMI_SAS_DRIVE_STATUS_OFFLINE     4
+-#define CSMI_SAS_DRIVE_STATUS_QUEUED_FOR_REBUILD 5
+-
+-// RAID Drive Usage
+-// (bDriveUsage)
+-#define CSMI_SAS_DRIVE_CONFIG_NOT_USED      0
+-#define CSMI_SAS_DRIVE_CONFIG_MEMBER        1
+-#define CSMI_SAS_DRIVE_CONFIG_SPARE         2
+-#define CSMI_SAS_DRIVE_CONFIG_SPARE_ACTIVE  3
+-
+-// RAID Drive Type
+-// (bDriveType)
+-#define CSMI_SAS_DRIVE_TYPE_UNKNOWN         0
+-#define CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS 1
+-#define CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS   2
+-#define CSMI_SAS_DRIVE_TYPE_SATA            3
+-#define CSMI_SAS_DRIVE_TYPE_SATA_PS         4
+-#define CSMI_SAS_DRIVE_TYPE_OTHER           255
+-
+-// RAID Write Protect
+-// (bWriteProtect)
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN     0
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNCHANGED   0
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_ENABLED     1
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_DISABLED    2
+-
+-// RAID Cache Setting
+-// (bCacheSetting)
+-#define CSMI_SAS_RAID_SET_CACHE_UNKNOWN             0
+-#define CSMI_SAS_RAID_SET_CACHE_UNCHANGED           0
+-#define CSMI_SAS_RAID_SET_CACHE_ENABLED             1
+-#define CSMI_SAS_RAID_SET_CACHE_DISABLED            2
+-#define CSMI_SAS_RAID_SET_CACHE_CORRUPT             3
+-
+-// RAID Features
+-// (uFeatures)
+-#define CSMI_SAS_RAID_FEATURE_TRANSFORMATION    0x00000001
+-#define CSMI_SAS_RAID_FEATURE_REBUILD           0x00000002
+-#define CSMI_SAS_RAID_FEATURE_SPLIT_MIRROR      0x00000004
+-#define CSMI_SAS_RAID_FEATURE_MERGE_MIRROR      0x00000008
+-#define CSMI_SAS_RAID_FEATURE_LUN_RENUMBER      0x00000010
+-#define CSMI_SAS_RAID_FEATURE_SURFACE_SCAN      0x00000020
+-#define CSMI_SAS_RAID_FEATURE_SPARES_SHARED     0x00000040
+-
+-// RAID Priority
+-// (bDefaultTransformPriority, etc.)
+-#define CSMI_SAS_PRIORITY_UNKNOWN   0
+-#define CSMI_SAS_PRIORITY_UNCHANGED 0
+-#define CSMI_SAS_PRIORITY_AUTO      1
+-#define CSMI_SAS_PRIORITY_OFF       2
+-#define CSMI_SAS_PRIORITY_LOW       3
+-#define CSMI_SAS_PRIORITY_MEDIUM    4
+-#define CSMI_SAS_PRIORITY_HIGH      5
+-
+-// RAID Transformation Rules
+-// (uRaidSetTransformationRules)
+-#define CSMI_SAS_RAID_RULE_AVAILABLE_MEMORY     0x00000001
+-#define CSMI_SAS_RAID_RULE_OVERLAPPED_EXTENTS   0x00000002
+-
+-// RAID Cache Ratios Supported
+-// (bCacheRatiosSupported)
+-// from 0 to 100 defines the write to read ratio, 0 is 100% write
+-#define CSMI_SAS_RAID_CACHE_RATIO_RANGE     101
+-#define CSMI_SAS_RAID_CACHE_RATIO_FIXED     102
+-#define CSMI_SAS_RAID_CACHE_RATIO_AUTO      103
+-#define CSMI_SAS_RAID_CACHE_RATIO_END       255
+-
+-// RAID Cache Ratio Flag
+-// (bCacheRatioFlag)
+-#define CSMI_SAS_RAID_CACHE_RATIO_DISABLE   0
+-#define CSMI_SAS_RAID_CACHE_RATIO_ENABLE    1
+-
+-// RAID Clear Configuration Signature
+-// (bClearConfiguration)
+-#define CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE "RAIDCLR"
+-
+-// RAID Failure Codes
+-// (uFailureCode)
+-#define CSMI_SAS_FAIL_CODE_OK                           0
+-#define CSMI_SAS_FAIL_CODE_PARAMETER_INVALID            1000
+-#define CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID   1001
+-#define CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID     1002
+-#define CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID          1003
+-#define CSMI_SAS_FAIL_CODE_SURFACE_SCAN_INVALID         1004
+-#define CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID  1005
+-#define CSMI_SAS_FAIL_CODE_ELEMENT_INDEX_INVALID        1006
+-#define CSMI_SAS_FAIL_CODE_SUBELEMENT_INDEX_INVALID     1007
+-#define CSMI_SAS_FAIL_CODE_EXTENT_INVALID               1008
+-#define CSMI_SAS_FAIL_CODE_BLOCK_COUNT_INVALID          1009
+-#define CSMI_SAS_FAIL_CODE_DRIVE_INDEX_INVALID          1010
+-#define CSMI_SAS_FAIL_CODE_EXISTING_LUN_INVALID         1011
+-#define CSMI_SAS_FAIL_CODE_RAID_TYPE_INVALID            1012
+-#define CSMI_SAS_FAIL_CODE_STRIPE_SIZE_INVALID          1013
+-#define CSMI_SAS_FAIL_CODE_TRANSFORMATION_INVALID       1014
+-#define CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID         1015
+-#define CSMI_SAS_FAIL_CODE_ENUMERATION_TYPE_INVALID     1016
+-
+-#define CSMI_SAS_FAIL_CODE_EXCEEDED_RAID_SET_COUNT      2000
+-#define CSMI_SAS_FAIL_CODE_DUPLICATE_LUN                2001
+-
+-#define CSMI_SAS_FAIL_CODE_WAIT_FOR_OPERATION           3000
+-
+-// RAID Enumeration Types
+-// (uEnumerationType)
+-#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE                0
+-#define CSMI_SAS_RAID_ELEMENT_TYPE_MODULE               1
+-#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE_RAID_SET       2
+-#define CSMI_SAS_RAID_ELEMENT_TYPE_EXTENT_DRIVE         3
+-
+-// RAID Extent Types
+-// (bExtentType)
+-#define CSMI_SAS_RAID_EXTENT_RESERVED       0
+-#define CSMI_SAS_RAID_EXTENT_METADATA       1
+-#define CSMI_SAS_RAID_EXTENT_ALLOCATED      2
+-#define CSMI_SAS_RAID_EXTENT_UNALLOCATED    3
+-
+-// RAID Operation Types
+-// (uOperationType)
+-#define CSMI_SAS_RAID_SET_CREATE            0
+-#define CSMI_SAS_RAID_SET_LABEL             1
+-#define CSMI_SAS_RAID_SET_TRANSFORM         2
+-#define CSMI_SAS_RAID_SET_DELETE            3
+-#define CSMI_SAS_RAID_SET_WRITE_PROTECT     4
+-#define CSMI_SAS_RAID_SET_CACHE             5
+-#define CSMI_SAS_RAID_SET_ONLINE_STATE      6
+-#define CSMI_SAS_RAID_SET_SPARE             7
+-
+-// RAID Transform Types
+-// (bTransformType)
+-#define CSMI_SAS_RAID_SET_TRANSFORM_SPLIT_MIRROR    0
+-#define CSMI_SAS_RAID_SET_TRANSFORM_MERGE_RAID_0    1
+-#define CSMI_SAS_RAID_SET_TRANSFORM_LUN_RENUMBER    2
+-#define CSMI_SAS_RAID_SET_TRANSFORM_RAID_SET        3
+-
+-// RAID Online State
+-// (bOnlineState)
+-#define CSMI_SAS_RAID_SET_STATE_UNKNOWN     0
+-#define CSMI_SAS_RAID_SET_STATE_ONLINE      1
+-#define CSMI_SAS_RAID_SET_STATE_OFFLINE     2
+-
+-/* * * * * * * * * * SAS HBA Class IOCTL Constants * * * * * * * * * */
+-
+-// Return codes for SAS IOCTL's
+-// (IoctlHeader.ReturnCode)
+-
+-#define CSMI_SAS_PHY_INFO_CHANGED            CSMI_SAS_STATUS_SUCCESS
+-#define CSMI_SAS_PHY_INFO_NOT_CHANGEABLE     2000
+-#define CSMI_SAS_LINK_RATE_OUT_OF_RANGE      2001
+-
+-#define CSMI_SAS_PHY_DOES_NOT_EXIST          2002
+-#define CSMI_SAS_PHY_DOES_NOT_MATCH_PORT     2003
+-#define CSMI_SAS_PHY_CANNOT_BE_SELECTED      2004
+-#define CSMI_SAS_SELECT_PHY_OR_PORT          2005
+-#define CSMI_SAS_PORT_DOES_NOT_EXIST         2006
+-#define CSMI_SAS_PORT_CANNOT_BE_SELECTED     2007
+-#define CSMI_SAS_CONNECTION_FAILED           2008
+-
+-#define CSMI_SAS_NO_SATA_DEVICE              2009
+-#define CSMI_SAS_NO_SATA_SIGNATURE           2010
+-#define CSMI_SAS_SCSI_EMULATION              2011
+-#define CSMI_SAS_NOT_AN_END_DEVICE           2012
+-#define CSMI_SAS_NO_SCSI_ADDRESS             2013
+-#define CSMI_SAS_NO_DEVICE_ADDRESS           2014
+-
+-// Signature value
+-// (IoctlHeader.Signature)
+-
+-#define CSMI_SAS_SIGNATURE    "CSMISAS"
+-
+-// Timeout value default of 60 seconds
+-// (IoctlHeader.Timeout)
+-
+-#define CSMI_SAS_TIMEOUT      60
+-
+-// Device types
+-// (bDeviceType)
+-
+-#define CSMI_SAS_PHY_UNUSED               0x00
+-#define CSMI_SAS_NO_DEVICE_ATTACHED       0x00
+-#define CSMI_SAS_END_DEVICE               0x10
+-#define CSMI_SAS_EDGE_EXPANDER_DEVICE     0x20
+-#define CSMI_SAS_FANOUT_EXPANDER_DEVICE   0x30
+-
+-// Protocol options
+-// (bInitiatorPortProtocol, bTargetPortProtocol)
+-
+-#define CSMI_SAS_PROTOCOL_SATA   0x01
+-#define CSMI_SAS_PROTOCOL_SMP    0x02
+-#define CSMI_SAS_PROTOCOL_STP    0x04
+-#define CSMI_SAS_PROTOCOL_SSP    0x08
+-
+-// Negotiated and hardware link rates
+-// (bNegotiatedLinkRate, bMinimumLinkRate, bMaximumLinkRate)
+-
+-#define CSMI_SAS_LINK_RATE_UNKNOWN  0x00
+-#define CSMI_SAS_PHY_DISABLED       0x01
+-#define CSMI_SAS_LINK_RATE_FAILED   0x02
+-#define CSMI_SAS_SATA_SPINUP_HOLD   0x03
+-#define CSMI_SAS_SATA_PORT_SELECTOR 0x04
+-#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08
+-#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09
+-#define CSMI_SAS_LINK_VIRTUAL       0x10
+-
+-// Discover state
+-// (bAutoDiscover)
+-
+-#define CSMI_SAS_DISCOVER_NOT_SUPPORTED   0x00
+-#define CSMI_SAS_DISCOVER_NOT_STARTED     0x01
+-#define CSMI_SAS_DISCOVER_IN_PROGRESS     0x02
+-#define CSMI_SAS_DISCOVER_COMPLETE        0x03
+-#define CSMI_SAS_DISCOVER_ERROR           0x04
+-
+-// Phy features
+-
+-#define CSMI_SAS_PHY_VIRTUAL_SMP          0x01
+-
+-// Programmed link rates
+-// (bMinimumLinkRate, bMaximumLinkRate)
+-// (bProgrammedMinimumLinkRate, bProgrammedMaximumLinkRate)
+-
+-#define CSMI_SAS_PROGRAMMED_LINK_RATE_UNCHANGED 0x00
+-#define CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS  0x08
+-#define CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS  0x09
+-
+-// Link rate
+-// (bNegotiatedLinkRate in CSMI_SAS_SET_PHY_INFO)
+-
+-#define CSMI_SAS_LINK_RATE_NEGOTIATE      0x00
+-#define CSMI_SAS_LINK_RATE_PHY_DISABLED   0x01
+-
+-// Signal class
+-// (bSignalClass in CSMI_SAS_SET_PHY_INFO)
+-
+-#define CSMI_SAS_SIGNAL_CLASS_UNKNOWN     0x00
+-#define CSMI_SAS_SIGNAL_CLASS_DIRECT      0x01
+-#define CSMI_SAS_SIGNAL_CLASS_SERVER      0x02
+-#define CSMI_SAS_SIGNAL_CLASS_ENCLOSURE   0x03
+-
+-// Link error reset
+-// (bResetCounts)
+-
+-#define CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS   0x00
+-#define CSMI_SAS_LINK_ERROR_RESET_COUNTS        0x01
+-
+-// Phy identifier
+-// (bPhyIdentifier)
+-
+-#define CSMI_SAS_USE_PORT_IDENTIFIER   0xFF
+-
+-// Port identifier
+-// (bPortIdentifier)
+-
+-#define CSMI_SAS_IGNORE_PORT           0xFF
+-
+-// Programmed link rates
+-// (bConnectionRate)
+-
+-#define CSMI_SAS_LINK_RATE_NEGOTIATED  0x00
+-#define CSMI_SAS_LINK_RATE_1_5_GBPS    0x08
+-#define CSMI_SAS_LINK_RATE_3_0_GBPS    0x09
+-
+-// Connection status
+-// (bConnectionStatus)
+-
+-#define CSMI_SAS_OPEN_ACCEPT                          0
+-#define CSMI_SAS_OPEN_REJECT_BAD_DESTINATION          1
+-#define CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED       2
+-#define CSMI_SAS_OPEN_REJECT_NO_DESTINATION           3
+-#define CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED          4
+-#define CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED   5
+-#define CSMI_SAS_OPEN_REJECT_RESERVE_ABANDON          6
+-#define CSMI_SAS_OPEN_REJECT_RESERVE_CONTINUE         7
+-#define CSMI_SAS_OPEN_REJECT_RESERVE_INITIALIZE       8
+-#define CSMI_SAS_OPEN_REJECT_RESERVE_STOP             9
+-#define CSMI_SAS_OPEN_REJECT_RETRY                    10
+-#define CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY       11
+-#define CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION        12
+-
+-// SSP Status
+-// (bSSPStatus)
+-
+-#define CSMI_SAS_SSP_STATUS_UNKNOWN     0x00
+-#define CSMI_SAS_SSP_STATUS_WAITING     0x01
+-#define CSMI_SAS_SSP_STATUS_COMPLETED   0x02
+-#define CSMI_SAS_SSP_STATUS_FATAL_ERROR 0x03
+-#define CSMI_SAS_SSP_STATUS_RETRY       0x04
+-#define CSMI_SAS_SSP_STATUS_NO_TAG      0x05
+-
+-// SSP Flags
+-// (uFlags)
+-
+-#define CSMI_SAS_SSP_READ           0x00000001
+-#define CSMI_SAS_SSP_WRITE          0x00000002
+-#define CSMI_SAS_SSP_UNSPECIFIED    0x00000004
+-
+-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_SIMPLE         0x00000000
+-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE  0x00000010
+-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED        0x00000020
+-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA            0x00000040
+-
+-// SSP Data present
+-// (bDataPresent)
+-
+-#define CSMI_SAS_SSP_NO_DATA_PRESENT         0x00
+-#define CSMI_SAS_SSP_RESPONSE_DATA_PRESENT   0x01
+-#define CSMI_SAS_SSP_SENSE_DATA_PRESENT      0x02
+-
+-// STP Flags
+-// (uFlags)
+-
+-#define CSMI_SAS_STP_READ           0x00000001
+-#define CSMI_SAS_STP_WRITE          0x00000002
+-#define CSMI_SAS_STP_UNSPECIFIED    0x00000004
+-#define CSMI_SAS_STP_PIO            0x00000010
+-#define CSMI_SAS_STP_DMA            0x00000020
+-#define CSMI_SAS_STP_PACKET         0x00000040
+-#define CSMI_SAS_STP_DMA_QUEUED     0x00000080
+-#define CSMI_SAS_STP_EXECUTE_DIAG   0x00000100
+-#define CSMI_SAS_STP_RESET_DEVICE   0x00000200
+-
+-// Task Management Flags
+-// (uFlags)
+-
+-#define CSMI_SAS_TASK_IU               0x00000001
+-#define CSMI_SAS_HARD_RESET_SEQUENCE   0x00000002
+-#define CSMI_SAS_SUPPRESS_RESULT       0x00000004
+-
+-// Task Management Functions
+-// (bTaskManagement)
+-
+-#define CSMI_SAS_SSP_ABORT_TASK           0x01
+-#define CSMI_SAS_SSP_ABORT_TASK_SET       0x02
+-#define CSMI_SAS_SSP_CLEAR_TASK_SET       0x04
+-#define CSMI_SAS_SSP_LOGICAL_UNIT_RESET   0x08
+-#define CSMI_SAS_SSP_CLEAR_ACA            0x40
+-#define CSMI_SAS_SSP_QUERY_TASK           0x80
+-
+-// Task Management Information
+-// (uInformation)
+-
+-#define CSMI_SAS_SSP_TEST           1
+-#define CSMI_SAS_SSP_EXCEEDED       2
+-#define CSMI_SAS_SSP_DEMAND         3
+-#define CSMI_SAS_SSP_TRIGGER        4
+-
+-// Connector Pinout Information
+-// (uPinout)
+-
+-#define CSMI_SAS_CON_UNKNOWN              0x00000001
+-#define CSMI_SAS_CON_SFF_8482             0x00000002
+-#define CSMI_SAS_CON_SFF_8470_LANE_1      0x00000100
+-#define CSMI_SAS_CON_SFF_8470_LANE_2      0x00000200
+-#define CSMI_SAS_CON_SFF_8470_LANE_3      0x00000400
+-#define CSMI_SAS_CON_SFF_8470_LANE_4      0x00000800
+-#define CSMI_SAS_CON_SFF_8484_LANE_1      0x00010000
+-#define CSMI_SAS_CON_SFF_8484_LANE_2      0x00020000
+-#define CSMI_SAS_CON_SFF_8484_LANE_3      0x00040000
+-#define CSMI_SAS_CON_SFF_8484_LANE_4      0x00080000
+-
+-// Connector Location Information
+-// (bLocation)
+-
+-// same as uPinout above...
+-// #define CSMI_SAS_CON_UNKNOWN              0x01
+-#define CSMI_SAS_CON_INTERNAL             0x02
+-#define CSMI_SAS_CON_EXTERNAL             0x04
+-#define CSMI_SAS_CON_SWITCHABLE           0x08
+-#define CSMI_SAS_CON_AUTO                 0x10
+-#define CSMI_SAS_CON_NOT_PRESENT          0x20
+-#define CSMI_SAS_CON_NOT_CONNECTED        0x80
+-
+-// Device location identification
+-// (bIdentify)
+-
+-#define CSMI_SAS_LOCATE_UNKNOWN           0x00
+-#define CSMI_SAS_LOCATE_FORCE_OFF         0x01
+-#define CSMI_SAS_LOCATE_FORCE_ON          0x02
+-
+-// Location Valid flags
+-// (uLocationFlags)
+-
+-#define CSMI_SAS_LOCATE_SAS_ADDRESS_VALID           0x00000001
+-#define CSMI_SAS_LOCATE_SAS_LUN_VALID               0x00000002
+-#define CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID  0x00000004
+-#define CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID        0x00000008
+-#define CSMI_SAS_LOCATE_BAY_PREFIX_VALID            0x00000010
+-#define CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID        0x00000020
+-#define CSMI_SAS_LOCATE_LOCATION_STATE_VALID        0x00000040
+-
+-/* * * * * * * * SAS Phy Control Class IOCTL Constants * * * * * * * * */
+-
+-// Return codes for SAS Phy Control IOCTL's
+-// (IoctlHeader.ReturnCode)
+-
+-// Signature value
+-// (IoctlHeader.Signature)
+-
+-#define CSMI_PHY_SIGNATURE    "CSMIPHY"
+-
+-// Phy Control Functions
+-// (bFunction)
+-
+-// values 0x00 to 0xFF are consistent in definition with the SMP PHY CONTROL
+-// function defined in the SAS spec
+-#define CSMI_SAS_PC_NOP                   0x00000000
+-#define CSMI_SAS_PC_LINK_RESET            0x00000001
+-#define CSMI_SAS_PC_HARD_RESET            0x00000002
+-#define CSMI_SAS_PC_PHY_DISABLE           0x00000003
+-// 0x04 to 0xFF reserved...
+-#define CSMI_SAS_PC_GET_PHY_SETTINGS      0x00000100
+-
+-// Link Flags
+-#define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
+-#define CSMI_SAS_PHY_UPDATE_SPINUP_RATE   0x00000002
+-#define CSMI_SAS_PHY_AUTO_COMWAKE         0x00000004
+-
+-// Device Types for Phy Settings
+-// (bType)
+-#define CSMI_SAS_UNDEFINED 0x00
+-#define CSMI_SAS_SATA      0x01
+-#define CSMI_SAS_SAS       0x02
+-
+-// Transmitter Flags
+-// (uTransmitterFlags)
+-#define CSMI_SAS_PHY_PREEMPHASIS_DISABLED    0x00000001
+-
+-// Receiver Flags
+-// (uReceiverFlags)
+-#define CSMI_SAS_PHY_EQUALIZATION_DISABLED   0x00000001
+-
+-// Pattern Flags
+-// (uPatternFlags)
+-// #define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
+-#define CSMI_SAS_PHY_DISABLE_SCRAMBLING      0x00000002
+-#define CSMI_SAS_PHY_DISABLE_ALIGN           0x00000004
+-#define CSMI_SAS_PHY_DISABLE_SSC             0x00000008
+-
+-#define CSMI_SAS_PHY_FIXED_PATTERN           0x00000010
+-#define CSMI_SAS_PHY_USER_PATTERN            0x00000020
+-
+-// Fixed Patterns
+-// (bFixedPattern)
+-#define CSMI_SAS_PHY_CJPAT                   0x00000001
+-#define CSMI_SAS_PHY_ALIGN                   0x00000002
+-
+-// Type Flags
+-// (bTypeFlags)
+-#define CSMI_SAS_PHY_POSITIVE_DISPARITY      0x01
+-#define CSMI_SAS_PHY_NEGATIVE_DISPARITY      0x02
+-#define CSMI_SAS_PHY_CONTROL_CHARACTER       0x04
+-
+-// Miscellaneous
+-#define SLOT_NUMBER_UNKNOWN   0xFFFF
+-
+-/*************************************************************************/
+-/* DATA STRUCTURES                                                       */
+-/*************************************************************************/
+-
+-/* * * * * * * * * * Class Independent Structures * * * * * * * * * */
+-
+-// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
+-#pragma pack(8)
+-
+-// CC_CSMI_SAS_DRIVER_INFO
+-
+-typedef struct _CSMI_SAS_DRIVER_INFO {
+-   __u8  szName[81];
+-   __u8  szDescription[81];
+-   __u16 usMajorRevision;
+-   __u16 usMinorRevision;
+-   __u16 usBuildRevision;
+-   __u16 usReleaseRevision;
+-   __u16 usCSMIMajorRevision;
+-   __u16 usCSMIMinorRevision;
+-} CSMI_SAS_DRIVER_INFO,
+-  *PCSMI_SAS_DRIVER_INFO;
+-
+-typedef struct _CSMI_SAS_DRIVER_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_DRIVER_INFO Information;
+-} CSMI_SAS_DRIVER_INFO_BUFFER,
+-  *PCSMI_SAS_DRIVER_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_CNTLR_CONFIGURATION
+-
+-typedef struct _CSMI_SAS_PCI_BUS_ADDRESS {
+-   __u8  bBusNumber;
+-   __u8  bDeviceNumber;
+-   __u8  bFunctionNumber;
+-   __u8  bReserved;
+-} CSMI_SAS_PCI_BUS_ADDRESS,
+-  *PCSMI_SAS_PCI_BUS_ADDRESS;
+-
+-typedef union _CSMI_SAS_IO_BUS_ADDRESS {
+-   CSMI_SAS_PCI_BUS_ADDRESS PciAddress;
+-   __u8  bReserved[32];
+-} CSMI_SAS_IO_BUS_ADDRESS,
+-  *PCSMI_SAS_IO_BUS_ADDRESS;
+-
+-typedef struct _CSMI_SAS_CNTLR_CONFIG {
+-   __u32 uBaseIoAddress;
+-   struct {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } BaseMemoryAddress;
+-   __u32 uBoardID;
+-   __u16 usSlotNumber;
+-   __u8  bControllerClass;
+-   __u8  bIoBusType;
+-   CSMI_SAS_IO_BUS_ADDRESS BusAddress;
+-   __u8  szSerialNumber[81];
+-   __u16 usMajorRevision;
+-   __u16 usMinorRevision;
+-   __u16 usBuildRevision;
+-   __u16 usReleaseRevision;
+-   __u16 usBIOSMajorRevision;
+-   __u16 usBIOSMinorRevision;
+-   __u16 usBIOSBuildRevision;
+-   __u16 usBIOSReleaseRevision;
+-   __u32 uControllerFlags;
+-   __u16 usRromMajorRevision;
+-   __u16 usRromMinorRevision;
+-   __u16 usRromBuildRevision;
+-   __u16 usRromReleaseRevision;
+-   __u16 usRromBIOSMajorRevision;
+-   __u16 usRromBIOSMinorRevision;
+-   __u16 usRromBIOSBuildRevision;
+-   __u16 usRromBIOSReleaseRevision;
+-   __u8  bReserved[7];
+-} CSMI_SAS_CNTLR_CONFIG,
+-  *PCSMI_SAS_CNTLR_CONFIG;
+-
+-typedef struct _CSMI_SAS_CNTLR_CONFIG_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_CNTLR_CONFIG Configuration;
+-} CSMI_SAS_CNTLR_CONFIG_BUFFER,
+-  *PCSMI_SAS_CNTLR_CONFIG_BUFFER;
+-
+-// CC_CSMI_SAS_CNTLR_STATUS
+-
+-typedef struct _CSMI_SAS_CNTLR_STATUS {
+-   __u32 uStatus;
+-   __u32 uOfflineReason;
+-   __u8  bReserved[28];
+-} CSMI_SAS_CNTLR_STATUS,
+-  *PCSMI_SAS_CNTLR_STATUS;
+-
+-typedef struct _CSMI_SAS_CNTLR_STATUS_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_CNTLR_STATUS Status;
+-} CSMI_SAS_CNTLR_STATUS_BUFFER,
+-  *PCSMI_SAS_CNTLR_STATUS_BUFFER;
+-
+-// CC_CSMI_SAS_FIRMWARE_DOWNLOAD
+-
+-typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD {
+-   __u32 uBufferLength;
+-   __u32 uDownloadFlags;
+-   __u8  bReserved[32];
+-   __u16 usStatus;
+-   __u16 usSeverity;
+-} CSMI_SAS_FIRMWARE_DOWNLOAD,
+-  *PCSMI_SAS_FIRMWARE_DOWNLOAD;
+-
+-typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_FIRMWARE_DOWNLOAD Information;
+-   __u8  bDataBuffer[1];
+-} CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER,
+-  *PCSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER;
+-
+-// CC_CSMI_SAS_RAID_INFO
+-
+-typedef struct _CSMI_SAS_RAID_INFO {
+-   __u32 uNumRaidSets;
+-   __u32 uMaxDrivesPerSet;
+-   __u32 uMaxRaidSets;
+-   __u8  bMaxRaidTypes;
+-   __u8  bReservedByteFields[7];
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulMinRaidSetBlocks;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulMaxRaidSetBlocks;
+-   __u32 uMaxPhysicalDrives;
+-   __u32 uMaxExtents;
+-   __u32 uMaxModules;
+-   __u32 uMaxTransformationMemory;
+-   __u32 uChangeCount;
+-   __u8  bReserved[44];
+-} CSMI_SAS_RAID_INFO,
+-  *PCSMI_SAS_RAID_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_INFO Information;
+-} CSMI_SAS_RAID_INFO_BUFFER,
+-  *PCSMI_SAS_RAID_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_GET_RAID_CONFIG
+-
+-typedef struct _CSMI_SAS_RAID_DRIVES {
+-   __u8  bModel[40];
+-   __u8  bFirmware[8];
+-   __u8  bSerialNumber[40];
+-   __u8  bSASAddress[8];
+-   __u8  bSASLun[8];
+-   __u8  bDriveStatus;
+-   __u8  bDriveUsage;
+-   __u16 usBlockSize;
+-   __u8  bDriveType;
+-   __u8  bReserved[15];
+-   __u32 uDriveIndex;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulTotalUserBlocks;
+-} CSMI_SAS_RAID_DRIVES,
+-  *PCSMI_SAS_RAID_DRIVES;
+-
+-typedef struct _CSMI_SAS_RAID_DEVICE_ID {
+-   __u8  bDeviceIdentificationVPDPage[1];
+-} CSMI_SAS_RAID_DEVICE_ID,
+-  *PCSMI_SAS_RAID_DEVICE_ID;
+-
+-typedef struct _CSMI_SAS_RAID_SET_ADDITIONAL_DATA {
+-   __u8  bLabel[16];
+-   __u8  bRaidSetLun[8];
+-   __u8  bWriteProtection;
+-   __u8  bCacheSetting;
+-   __u8  bCacheRatio;
+-   __u16 usBlockSize;
+-   __u8  bReservedBytes[11];
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetExtentOffset;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetBlocks;
+-   __u32 uStripeSizeInBlocks;
+-   __u32 uSectorsPerTrack;
+-   __u8  bApplicationScratchPad[16];
+-   __u32 uNumberOfHeads;
+-   __u32 uNumberOfTracks;
+-   __u8  bReserved[24];
+-} CSMI_SAS_RAID_SET_ADDITIONAL_DATA,
+-  *PCSMI_SAS_RAID_SET_ADDITIONAL_DATA;
+-
+-typedef struct _CSMI_SAS_RAID_CONFIG {
+-   __u32 uRaidSetIndex;
+-   __u32 uCapacity;
+-   __u32 uStripeSize;
+-   __u8  bRaidType;
+-   __u8  bStatus;
+-   __u8  bInformation;
+-   __u8  bDriveCount;
+-   __u8  bDataType;
+-   __u8  bReserved[11];
+-   __u32 uFailureCode;
+-   __u32 uChangeCount;
+-   union {
+-      CSMI_SAS_RAID_DRIVES Drives[1];
+-      CSMI_SAS_RAID_DEVICE_ID DeviceId[1];
+-      CSMI_SAS_RAID_SET_ADDITIONAL_DATA Data[1];
+-   };
+-} CSMI_SAS_RAID_CONFIG,
+-   *PCSMI_SAS_RAID_CONFIG;
+-
+-typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_CONFIG Configuration;
+-} CSMI_SAS_RAID_CONFIG_BUFFER,
+-  *PCSMI_SAS_RAID_CONFIG_BUFFER;
+-
+-// CC_CSMI_SAS_GET_RAID_FEATURES
+-
+-typedef struct _CSMI_SAS_RAID_TYPE_DESCRIPTION {
+-  __u8  bRaidType;
+-  __u8  bReservedBytes[7];
+-  __u32 uSupportedStripeSizeMap;
+-  __u8  bReserved[24];
+-} CSMI_SAS_RAID_TYPE_DESCRIPTION,
+-  *PCSMI_SAS_RAID_TYPE_DESCRIPTION;
+-
+-typedef struct _CSMI_SAS_RAID_FEATURES {
+-   __u32 uFeatures;
+-   __u8  bReservedFeatures[32];
+-   __u8  bDefaultTransformPriority;
+-   __u8  bTransformPriority;
+-   __u8  bDefaultRebuildPriority;
+-   __u8  bRebuildPriority;
+-   __u8  bDefaultSurfaceScanPriority;
+-   __u8  bSurfaceScanPriority;
+-   __u16 usReserved;
+-   __u32 uRaidSetTransformationRules;
+-   __u32 uReserved[11];
+-   CSMI_SAS_RAID_TYPE_DESCRIPTION RaidType[24];
+-   __u8  bCacheRatiosSupported[104];
+-   __u32 uChangeCount;
+-   __u32 uFailureCode;
+-   __u8  bReserved[120];
+-} CSMI_SAS_RAID_FEATURES,
+-  *PCSMI_SAS_RAID_FEATURES;
+-
+-typedef struct _CSMI_SAS_RAID_FEATURES_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_FEATURES Information;
+-} CSMI_SAS_RAID_FEATURES_BUFFER,
+-  *PCSMI_SAS_RAID_FEATURES_BUFFER;
+-
+-// CC_CSMI_SAS_SET_RAID_CONTROL
+-
+-typedef struct _CSMI_SAS_RAID_CONTROL {
+-   __u8  bTransformPriority;
+-   __u8  bRebuildPriority;
+-   __u8  bCacheRatioFlag;
+-   __u8  bCacheRatio;
+-   __u8  bSurfaceScanPriority;
+-   __u8  bReservedBytes[15];
+-   __u8  bClearConfiguration[8];
+-   __u32 uChangeCount;
+-   __u8  bReserved[88];
+-   __u32 uFailureCode;
+-   __u8  bFailureDescription[80];
+-} CSMI_SAS_RAID_CONTROL,
+-  *PCSMI_SAS_RAID_CONTROL;
+-
+-typedef struct _CSMI_SAS_RAID_CONTROL_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_CONTROL Information;
+-} CSMI_SAS_RAID_CONTROL_BUFFER,
+-  *PCSMI_SAS_RAID_CONTROL_BUFFER;
+-
+-// CC_CSMI_SAS_GET_RAID_ELEMENT
+-
+-typedef struct _CSMI_SAS_DRIVE_EXTENT_INFO {
+-   __u32 uDriveIndex;
+-   __u8  bExtentType;
+-   __u8  bReservedBytes[7];
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulExtentOffset;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulExtentBlocks;
+-   __u32 uRaidSetIndex;
+-   __u8  bReserved[96];
+-} CSMI_SAS_DRIVE_EXTENT_INFO,
+-  *PCSMI_SAS_DRIVE_EXTENT_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_MODULE_INFO {
+-   __u8  bReserved[128];
+-} CSMI_SAS_RAID_MODULE_INFO,
+-  *PCSMI_SAS_RAID_MODULE_INFO;
+-
+-typedef struct _CSMI_SAS_DRIVE_LOCATION {
+-   __u8  bConnector[16];
+-   __u8  bBoxName[16];
+-   __u32 uBay;
+-   __u8  bReservedBytes[4];
+-   __u8  bAttachedSASAddress[8];
+-   __u8  bAttachedPhyIdentifier;
+-   __u8  bReserved[79];
+-} CSMI_SAS_DRIVE_LOCATION,
+-  *PCSMI_SAS_DRIVE_LOCATION;
+-
+-typedef struct _CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA {
+-   __u8  bNegotiatedLinkRate[2];
+-   __u8  bReserved[126];
+-} CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA,
+-  *PCSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA;
+-
+-typedef struct _CSMI_SAS_DRIVE_INFO {
+-   CSMI_SAS_RAID_DRIVES Device;
+-   CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA Data;
+-   CSMI_SAS_DRIVE_LOCATION Location;
+-   __u8  bReserved[16];
+-} CSMI_SAS_DRIVE_INFO,
+-  *PCSMI_SAS_DRIVE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_ELEMENT {
+-   __u32 uEnumerationType;
+-   __u32 uElementIndex;
+-   __u32 uNumElements;
+-   __u32 uChangeCount;
+-   __u32 uSubElementIndex;
+-   __u8  bReserved[32];
+-   __u32 uFailureCode;
+-   __u8  bFailureDescription[80];
+-   union {
+-       CSMI_SAS_DRIVE_INFO Drive;
+-       CSMI_SAS_RAID_MODULE_INFO Module;
+-       CSMI_SAS_DRIVE_EXTENT_INFO Extent;
+-   } Element;
+-} CSMI_SAS_RAID_ELEMENT,
+-  *PCSMI_SAS_RAID_ELEMENT;
+-
+-typedef struct _CSMI_SAS_RAID_ELEMENT_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_ELEMENT Information;
+-} CSMI_SAS_RAID_ELEMENT_BUFFER,
+-  *PCSMI_SAS_RAID_ELEMENT_BUFFER;
+-
+-// CC_CSMI_SAS_SET_RAID_OPERATION
+-
+-typedef struct _CSMI_SAS_RAID_SET_LIST {
+-   __u32 uRaidSetIndex;
+-   __u8  bExistingLun[8];
+-   __u8  bNewLun[8];
+-   __u8  bReserved[12];
+-} CSMI_SAS_RAID_SET_LIST,
+-  *PCSMI_SAS_RAID_SET_LIST;
+-
+-typedef struct _CSMI_SAS_RAID_SET_DRIVE_LIST {
+-   __u32 uDriveIndex;
+-   __u8  bDriveUsage;
+-   __u8  bReserved[27];
+-} CSMI_SAS_RAID_SET_DRIVE_LIST,
+-  *PCSMI_SAS_RAID_SET_DRIVE_LIST;
+-
+-typedef struct _CSMI_SAS_RAID_SET_SPARE_INFO {
+-   __u32 uRaidSetIndex;
+-   __u32 uDriveCount;
+-   __u8  bApplicationScratchPad[16];
+-   __u8  bReserved[104];
+-} CSMI_SAS_RAID_SET_SPARE_INFO,
+-  *PCSMI_SAS_RAID_SET_SPARE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_ONLINE_STATE_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bOnlineState;
+-   __u8  bReserved[123];
+-} CSMI_SAS_RAID_SET_ONLINE_STATE_INFO,
+-  *PCSMI_SAS_RAID_SET_ONLINE_STATE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_CACHE_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bCacheSetting;
+-   __u8  bCacheRatioFlag;
+-   __u8  bCacheRatio;
+-   __u8  bReserved[121];
+-} CSMI_SAS_RAID_SET_CACHE_INFO,
+-  *PCSMI_SAS_RAID_SET_CACHE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bWriteProtectSetting;
+-   __u8  bReserved[123];
+-} CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO,
+-  *PCSMI_SAS_RAID_SET_WRITE_PROTECT_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_DELETE_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bReserved[124];
+-} CSMI_SAS_RAID_SET_DELETE_INFO,
+-  *PCSMI_SAS_RAID_SET_DELETE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_MODIFY_INFO {
+-   __u8  bRaidType;
+-   __u8  bReservedBytes[7];
+-   __u32 uStripeSize;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetBlocks;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetExtentOffset;
+-   __u32 uDriveCount;
+-   __u8  bReserved[96];
+-} CSMI_SAS_RAID_SET_MODIFY_INFO,
+-  *PCSMI_SAS_RAID_SET_MODIFY_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_TRANSFORM_INFO {
+-   __u8  bTransformType;
+-   __u8  bReservedBytes[3];
+-   __u32 uRaidSetIndex;
+-   __u8  bRaidType;
+-   __u8  bReservedBytes2[11];
+-   __u32 uAdditionalRaidSetIndex;
+-   __u32 uRaidSetCount;
+-   __u8  bApplicationScratchPad[16];
+-   CSMI_SAS_RAID_SET_MODIFY_INFO Modify;
+-   __u8  bReserved[80];
+-} CSMI_SAS_RAID_SET_TRANSFORM_INFO,
+-  *PCSMI_SAS_RAID_SET_TRANSFORM_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_LABEL_INFO {
+-   __u32 uRaidSetIndex;
+-   __u8  bLabel[16];
+-   __u8  bReserved[108];
+-} CSMI_SAS_RAID_SET_LABEL_INFO,
+-  *PCSMI_SAS_RAID_SET_LABEL_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_CREATE_INFO {
+-   __u8  bRaidType;
+-   __u8  bReservedBytes[7];
+-   __u32 uStripeSize;
+-   __u32 uTrackSectorCount;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetBlocks;
+-   struct
+-   {
+-      __u32 uLowPart;
+-      __u32 uHighPart;
+-   } ulRaidSetExtentOffset;
+-   __u32 uDriveCount;
+-   __u8  bLabel[16];
+-   __u32 uRaidSetIndex;
+-   __u8  bApplicationScratchPad[16];
+-   __u32 uNumberOfHeads;
+-   __u32 uNumberOfTracks;
+-   __u8  bReserved[48];
+-} CSMI_SAS_RAID_SET_CREATE_INFO,
+-  *PCSMI_SAS_RAID_SET_CREATE_INFO;
+-
+-typedef struct _CSMI_SAS_RAID_SET_OPERATION {
+-   __u32 uOperationType;
+-   __u32 uChangeCount;
+-   __u32 uFailureCode;
+-   __u8  bFailureDescription[80];
+-   __u8  bReserved[28];
+-   union {
+-       CSMI_SAS_RAID_SET_CREATE_INFO Create;
+-       CSMI_SAS_RAID_SET_LABEL_INFO Label;
+-       CSMI_SAS_RAID_SET_TRANSFORM_INFO Transform;
+-       CSMI_SAS_RAID_SET_DELETE_INFO Delete;
+-       CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO Protect;
+-       CSMI_SAS_RAID_SET_CACHE_INFO Cache;
+-       CSMI_SAS_RAID_SET_ONLINE_STATE_INFO State;
+-       CSMI_SAS_RAID_SET_SPARE_INFO Spare;
+-   } Operation;
+-   union {
+-       CSMI_SAS_RAID_SET_DRIVE_LIST DriveList[1];
+-       CSMI_SAS_RAID_SET_LIST RaidSetList[1];
+-   } Parameters;
+-} CSMI_SAS_RAID_SET_OPERATION,
+-  *PCSMI_SAS_RAID_SET_OPERATION;
+-
+-typedef struct _CSMI_SAS_RAID_SET_OPERATION_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_RAID_SET_OPERATION Information;
+-} CSMI_SAS_RAID_SET_OPERATION_BUFFER,
+-  *PCSMI_SAS_RAID_SET_OPERATION_BUFFER;
+-
+-/* * * * * * * * * * SAS HBA Class Structures * * * * * * * * * */
+-
+-// CC_CSMI_SAS_GET_PHY_INFO
+-
+-typedef struct _CSMI_SAS_IDENTIFY {
+-   __u8  bDeviceType;
+-   __u8  bRestricted;
+-   __u8  bInitiatorPortProtocol;
+-   __u8  bTargetPortProtocol;
+-   __u8  bRestricted2[8];
+-   __u8  bSASAddress[8];
+-   __u8  bPhyIdentifier;
+-   __u8  bSignalClass;
+-   __u8  bReserved[6];
+-} CSMI_SAS_IDENTIFY,
+-  *PCSMI_SAS_IDENTIFY;
+-
+-typedef struct _CSMI_SAS_PHY_ENTITY {
+-   CSMI_SAS_IDENTIFY Identify;
+-   __u8  bPortIdentifier;
+-   __u8  bNegotiatedLinkRate;
+-   __u8  bMinimumLinkRate;
+-   __u8  bMaximumLinkRate;
+-   __u8  bPhyChangeCount;
+-   __u8  bAutoDiscover;
+-   __u8  bPhyFeatures;
+-   __u8  bReserved;
+-   CSMI_SAS_IDENTIFY Attached;
+-} CSMI_SAS_PHY_ENTITY,
+-  *PCSMI_SAS_PHY_ENTITY;
+-
+-typedef struct _CSMI_SAS_PHY_INFO {
+-   __u8  bNumberOfPhys;
+-   __u8  bReserved[3];
+-   CSMI_SAS_PHY_ENTITY Phy[32];
+-} CSMI_SAS_PHY_INFO,
+-  *PCSMI_SAS_PHY_INFO;
+-
+-typedef struct _CSMI_SAS_PHY_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_PHY_INFO Information;
+-} CSMI_SAS_PHY_INFO_BUFFER,
+-  *PCSMI_SAS_PHY_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_SET_PHY_INFO
+-
+-typedef struct _CSMI_SAS_SET_PHY_INFO {
+-   __u8  bPhyIdentifier;
+-   __u8  bNegotiatedLinkRate;
+-   __u8  bProgrammedMinimumLinkRate;
+-   __u8  bProgrammedMaximumLinkRate;
+-   __u8  bSignalClass;
+-   __u8  bReserved[3];
+-} CSMI_SAS_SET_PHY_INFO,
+-  *PCSMI_SAS_SET_PHY_INFO;
+-
+-typedef struct _CSMI_SAS_SET_PHY_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SET_PHY_INFO Information;
+-} CSMI_SAS_SET_PHY_INFO_BUFFER,
+-  *PCSMI_SAS_SET_PHY_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_GET_LINK_ERRORS
+-
+-typedef struct _CSMI_SAS_LINK_ERRORS {
+-   __u8  bPhyIdentifier;
+-   __u8  bResetCounts;
+-   __u8  bReserved[2];
+-   __u32 uInvalidDwordCount;
+-   __u32 uRunningDisparityErrorCount;
+-   __u32 uLossOfDwordSyncCount;
+-   __u32 uPhyResetProblemCount;
+-} CSMI_SAS_LINK_ERRORS,
+-  *PCSMI_SAS_LINK_ERRORS;
+-
+-typedef struct _CSMI_SAS_LINK_ERRORS_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_LINK_ERRORS Information;
+-} CSMI_SAS_LINK_ERRORS_BUFFER,
+-  *PCSMI_SAS_LINK_ERRORS_BUFFER;
+-
+-// CC_CSMI_SAS_SMP_PASSTHRU
+-
+-typedef struct _CSMI_SAS_SMP_REQUEST {
+-   __u8  bFrameType;
+-   __u8  bFunction;
+-   __u8  bReserved[2];
+-   __u8  bAdditionalRequestBytes[1016];
+-} CSMI_SAS_SMP_REQUEST,
+-  *PCSMI_SAS_SMP_REQUEST;
+-
+-typedef struct _CSMI_SAS_SMP_RESPONSE {
+-   __u8  bFrameType;
+-   __u8  bFunction;
+-   __u8  bFunctionResult;
+-   __u8  bReserved;
+-   __u8  bAdditionalResponseBytes[1016];
+-} CSMI_SAS_SMP_RESPONSE,
+-  *PCSMI_SAS_SMP_RESPONSE;
+-
+-typedef struct _CSMI_SAS_SMP_PASSTHRU {
+-   __u8  bPhyIdentifier;
+-   __u8  bPortIdentifier;
+-   __u8  bConnectionRate;
+-   __u8  bReserved;
+-   __u8  bDestinationSASAddress[8];
+-   __u32 uRequestLength;
+-   CSMI_SAS_SMP_REQUEST Request;
+-   __u8  bConnectionStatus;
+-   __u8  bReserved2[3];
+-   __u32 uResponseBytes;
+-   CSMI_SAS_SMP_RESPONSE Response;
+-} CSMI_SAS_SMP_PASSTHRU,
+-  *PCSMI_SAS_SMP_PASSTHRU;
+-
+-typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SMP_PASSTHRU Parameters;
+-} CSMI_SAS_SMP_PASSTHRU_BUFFER,
+-  *PCSMI_SAS_SMP_PASSTHRU_BUFFER;
+-
+-// CC_CSMI_SAS_SSP_PASSTHRU
+-
+-typedef struct _CSMI_SAS_SSP_PASSTHRU {
+-   __u8  bPhyIdentifier;
+-   __u8  bPortIdentifier;
+-   __u8  bConnectionRate;
+-   __u8  bReserved;
+-   __u8  bDestinationSASAddress[8];
+-   __u8  bLun[8];
+-   __u8  bCDBLength;
+-   __u8  bAdditionalCDBLength;
+-   __u8  bReserved2[2];
+-   __u8  bCDB[16];
+-   __u32 uFlags;
+-   __u8  bAdditionalCDB[24];
+-   __u32 uDataLength;
+-} CSMI_SAS_SSP_PASSTHRU,
+-  *PCSMI_SAS_SSP_PASSTHRU;
+-
+-typedef struct _CSMI_SAS_SSP_PASSTHRU_STATUS {
+-   __u8  bConnectionStatus;
+-   __u8  bSSPStatus;
+-   __u8  bReserved[2];
+-   __u8  bDataPresent;
+-   __u8  bStatus;
+-   __u8  bResponseLength[2];
+-   __u8  bResponse[256];
+-   __u32 uDataBytes;
+-} CSMI_SAS_SSP_PASSTHRU_STATUS,
+-  *PCSMI_SAS_SSP_PASSTHRU_STATUS;
+-
+-typedef struct _CSMI_SAS_SSP_PASSTHRU_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SSP_PASSTHRU Parameters;
+-   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
+-   __u8  bDataBuffer[1];
+-} CSMI_SAS_SSP_PASSTHRU_BUFFER,
+-  *PCSMI_SAS_SSP_PASSTHRU_BUFFER;
+-
+-// CC_CSMI_SAS_STP_PASSTHRU
+-
+-typedef struct _CSMI_SAS_STP_PASSTHRU {
+-   __u8  bPhyIdentifier;
+-   __u8  bPortIdentifier;
+-   __u8  bConnectionRate;
+-   __u8  bReserved;
+-   __u8  bDestinationSASAddress[8];
+-   __u8  bReserved2[4];
+-   __u8  bCommandFIS[20];
+-   __u32 uFlags;
+-   __u32 uDataLength;
+-} CSMI_SAS_STP_PASSTHRU,
+-  *PCSMI_SAS_STP_PASSTHRU;
+-
+-typedef struct _CSMI_SAS_STP_PASSTHRU_STATUS {
+-   __u8  bConnectionStatus;
+-   __u8  bReserved[3];
+-   __u8  bStatusFIS[20];
+-   __u32 uSCR[16];
+-   __u32 uDataBytes;
+-} CSMI_SAS_STP_PASSTHRU_STATUS,
+-  *PCSMI_SAS_STP_PASSTHRU_STATUS;
+-
+-typedef struct _CSMI_SAS_STP_PASSTHRU_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_STP_PASSTHRU Parameters;
+-   CSMI_SAS_STP_PASSTHRU_STATUS Status;
+-   __u8  bDataBuffer[1];
+-} CSMI_SAS_STP_PASSTHRU_BUFFER,
+-  *PCSMI_SAS_STP_PASSTHRU_BUFFER;
+-
+-// CC_CSMI_SAS_GET_SATA_SIGNATURE
+-
+-typedef struct _CSMI_SAS_SATA_SIGNATURE {
+-   __u8  bPhyIdentifier;
+-   __u8  bReserved[3];
+-   __u8  bSignatureFIS[20];
+-} CSMI_SAS_SATA_SIGNATURE,
+-  *PCSMI_SAS_SATA_SIGNATURE;
+-
+-typedef struct _CSMI_SAS_SATA_SIGNATURE_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SATA_SIGNATURE Signature;
+-} CSMI_SAS_SATA_SIGNATURE_BUFFER,
+-  *PCSMI_SAS_SATA_SIGNATURE_BUFFER;
+-
+-// CC_CSMI_SAS_GET_SCSI_ADDRESS
+-
+-typedef struct _CSMI_SAS_GET_SCSI_ADDRESS_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   __u8  bSASAddress[8];
+-   __u8  bSASLun[8];
+-   __u8  bHostIndex;
+-   __u8  bPathId;
+-   __u8  bTargetId;
+-   __u8  bLun;
+-} CSMI_SAS_GET_SCSI_ADDRESS_BUFFER,
+-   *PCSMI_SAS_GET_SCSI_ADDRESS_BUFFER;
+-
+-// CC_CSMI_SAS_GET_DEVICE_ADDRESS
+-
+-typedef struct _CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   __u8  bHostIndex;
+-   __u8  bPathId;
+-   __u8  bTargetId;
+-   __u8  bLun;
+-   __u8  bSASAddress[8];
+-   __u8  bSASLun[8];
+-} CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER,
+-  *PCSMI_SAS_GET_DEVICE_ADDRESS_BUFFER;
+-
+-// CC_CSMI_SAS_TASK_MANAGEMENT
+-
+-typedef struct _CSMI_SAS_SSP_TASK_IU {
+-   __u8  bHostIndex;
+-   __u8  bPathId;
+-   __u8  bTargetId;
+-   __u8  bLun;
+-   __u32 uFlags;
+-   __u32 uQueueTag;
+-   __u32 uReserved;
+-   __u8  bTaskManagementFunction;
+-   __u8  bReserved[7];
+-   __u32 uInformation;
+-} CSMI_SAS_SSP_TASK_IU,
+-  *PCSMI_SAS_SSP_TASK_IU;
+-
+-typedef struct _CSMI_SAS_SSP_TASK_IU_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_SSP_TASK_IU Parameters;
+-   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
+-} CSMI_SAS_SSP_TASK_IU_BUFFER,
+-  *PCSMI_SAS_SSP_TASK_IU_BUFFER;
+-
+-// CC_CSMI_SAS_GET_CONNECTOR_INFO
+-
+-typedef struct _CSMI_SAS_GET_CONNECTOR_INFO {
+-   __u32 uPinout;
+-   __u8  bConnector[16];
+-   __u8  bLocation;
+-   __u8  bReserved[15];
+-} CSMI_SAS_CONNECTOR_INFO,
+-  *PCSMI_SAS_CONNECTOR_INFO;
+-
+-typedef struct _CSMI_SAS_CONNECTOR_INFO_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   CSMI_SAS_CONNECTOR_INFO Reference[32];
+-} CSMI_SAS_CONNECTOR_INFO_BUFFER,
+-  *PCSMI_SAS_CONNECTOR_INFO_BUFFER;
+-
+-// CC_CSMI_SAS_GET_LOCATION
+-
+-typedef struct _CSMI_SAS_LOCATION_IDENTIFIER {
+-   __u32 bLocationFlags;
+-   __u8  bSASAddress[8];
+-   __u8  bSASLun[8];
+-   __u8  bEnclosureIdentifier[8];
+-   __u8  bEnclosureName[32];
+-   __u8  bBayPrefix[32];
+-   __u8  bBayIdentifier;
+-   __u8  bLocationState;
+-   __u8  bReserved[2];
+-} CSMI_SAS_LOCATION_IDENTIFIER,
+-  *PCSMI_SAS_LOCATION_IDENTIFIER;
+-
+-typedef struct _CSMI_SAS_GET_LOCATION_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   __u8  bHostIndex;
+-   __u8  bPathId;
+-   __u8  bTargetId;
+-   __u8  bLun;
+-   __u8  bIdentify;
+-   __u8  bNumberOfLocationIdentifiers;
+-   __u8  bLengthOfLocationIdentifier;
+-   CSMI_SAS_LOCATION_IDENTIFIER Location[1];
+-} CSMI_SAS_GET_LOCATION_BUFFER,
+-  *PCSMI_SAS_GET_LOCATION_BUFFER;
+-
+-// CC_CSMI_SAS_PHY_CONTROL
+-
+-typedef struct _CSMI_SAS_CHARACTER {
+-   __u8  bTypeFlags;
+-   __u8  bValue;
+-} CSMI_SAS_CHARACTER,
+-  *PCSMI_SAS_CHARACTER;
+-
+-typedef struct _CSMI_SAS_PHY_CONTROL {
+-   __u8  bType;
+-   __u8  bRate;
+-   __u8  bReserved[6];
+-   __u32 uVendorUnique[8];
+-   __u32 uTransmitterFlags;
+-   __i8  bTransmitAmplitude;
+-   __i8  bTransmitterPreemphasis;
+-   __i8  bTransmitterSlewRate;
+-   __i8  bTransmitterReserved[13];
+-   __u8  bTransmitterVendorUnique[64];
+-   __u32 uReceiverFlags;
+-   __i8  bReceiverThreshold;
+-   __i8  bReceiverEqualizationGain;
+-   __i8  bReceiverReserved[14];
+-   __u8  bReceiverVendorUnique[64];
+-   __u32 uPatternFlags;
+-   __u8  bFixedPattern;
+-   __u8  bUserPatternLength;
+-   __u8  bPatternReserved[6];
+-   CSMI_SAS_CHARACTER UserPatternBuffer[16];
+-} CSMI_SAS_PHY_CONTROL,
+-  *PCSMI_SAS_PHY_CONTROL;
+-
+-typedef struct _CSMI_SAS_PHY_CONTROL_BUFFER {
+-   IOCTL_HEADER IoctlHeader;
+-   __u32 uFunction;
+-   __u8  bPhyIdentifier;
+-   __u16 usLengthOfControl;
+-   __u8  bNumberOfControls;
+-   __u8  bReserved[4];
+-   __u32 uLinkFlags;
+-   __u8  bSpinupRate;
+-   __u8  bLinkReserved[7];
+-   __u32 uVendorUnique[8];
+-   CSMI_SAS_PHY_CONTROL Control[1];
+-} CSMI_SAS_PHY_CONTROL_BUFFER,
+-  *PCSMI_SAS_PHY_CONTROL_BUFFER;
+-
+-//EDM #pragma CSMI_SAS_END_PACK
+-#pragma pack()
+-
+-#endif // _CSMI_SAS_H_
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.c linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.c        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.c       2007-11-02 09:10:23.000000000 +0100
+@@ -0,0 +1,5095 @@
++#define mptctl_is_this_sas_cntr(ioc) (ioc->bus_type == SAS) ? 1 : 0
++
++#ifndef TRUE
++#define TRUE     (1)
++#endif
++#ifndef FALSE
++#define FALSE    (0)
++#endif
++
++#ifdef QUIESE_IO
++static int mptctl_raid_get_volume_id(MPT_ADAPTER *ioc, u8 PhysDiskNum, u8 *VolumeID,
++    u8 *VolumeBus);
++#endif
++static int mptctl_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus,
++    u8 VolumeId, pMpiRaidActionReply_t reply);
++static u8  map_sas_status_to_csmi(u8 mpi_sas_status);
++
++static u64 reverse_byte_order64(u64 * data64)
++{
++      int i;
++      u64 rc;
++      u8  * inWord = (u8 *)data64, * outWord = (u8 *)&rc;
++
++      for (i=0;i<8;i++) outWord[i] = inWord[7-i];
++
++      return rc;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Routine for the CSMI Sas Get Driver Info command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_driver_info(unsigned long arg)
++{
++
++      CSMI_SAS_DRIVER_INFO_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_DRIVER_INFO_BUFFER     karg;
++      MPT_ADAPTER     *ioc = NULL;
++      int             iocnum;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s - "
++            "Unable to read in csmi_sas_get_driver_info_buffer struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Fill in the data and return the structure to the calling
++       * program
++       */
++      memcpy( karg.Information.szName, MPT_MISCDEV_BASENAME,
++          sizeof(MPT_MISCDEV_BASENAME));
++      memcpy( karg.Information.szDescription, MPT_CSMI_DESCRIPTION,
++          sizeof(MPT_CSMI_DESCRIPTION));
++
++      karg.Information.usMajorRevision = MPT_LINUX_MAJOR_VERSION;
++      karg.Information.usMinorRevision = MPT_LINUX_MINOR_VERSION;
++      karg.Information.usBuildRevision = MPT_LINUX_BUILD_VERSION;
++      karg.Information.usReleaseRevision = MPT_LINUX_RELEASE_VERSION;
++
++      karg.Information.usCSMIMajorRevision = CSMI_MAJOR_REVISION;
++      karg.Information.usCSMIMinorRevision = CSMI_MINOR_REVISION;
++
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++              sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s - "
++                 "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI_SAS_GET_CNTLR_CONFIG command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_cntlr_config(unsigned long arg)
++{
++
++      CSMI_SAS_CNTLR_CONFIG_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_CNTLR_CONFIG_BUFFER    karg;
++      MPT_ADAPTER     *ioc = NULL;
++      int             iocnum;
++      int             ii;
++      unsigned int    reg;
++      u32             l;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_CONFIG_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s - "
++           "Unable to read in csmi_sas_get_cntlr_config_buffer struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++            "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Clear the struct before filling in data. */
++      memset( &karg.Configuration, 0, sizeof(CSMI_SAS_CNTLR_CONFIG));
++
++      /* Fill in the data and return the structure to the calling
++       * program
++       */
++
++      /* Get Base IO and Mem Mapped Addresses. */
++      for(ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
++              reg = PCI_BASE_ADDRESS_0 + (ii << 2);
++              pci_read_config_dword(ioc->pcidev, reg, &l);
++
++              if ((l & PCI_BASE_ADDRESS_SPACE) ==
++                  PCI_BASE_ADDRESS_SPACE_MEMORY) {
++                      karg.Configuration.BaseMemoryAddress.uLowPart =
++                          l & PCI_BASE_ADDRESS_MEM_MASK;
++              }
++              else {
++                      karg.Configuration.uBaseIoAddress =
++                          l & PCI_BASE_ADDRESS_IO_MASK;
++              }
++
++              if ((l & (PCI_BASE_ADDRESS_SPACE |
++                  PCI_BASE_ADDRESS_MEM_TYPE_MASK))
++                  == (PCI_BASE_ADDRESS_SPACE_MEMORY |
++                  PCI_BASE_ADDRESS_MEM_TYPE_64)) {
++                      pci_read_config_dword(ioc->pcidev, reg+4, &l);
++                      karg.Configuration.BaseMemoryAddress.uHighPart = l;
++              }
++              if ((l & PCI_BASE_ADDRESS_SPACE) ==
++                  PCI_BASE_ADDRESS_SPACE_MEMORY) {
++                      break;
++              }
++      }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
++      karg.Configuration.uBoardID = (ioc->pcidev->subsystem_device << 16) |
++          (ioc->pcidev->subsystem_vendor);
++#endif
++
++      karg.Configuration.usSlotNumber =
++          (ioc->pci_slot_number = 0xff) ?
++          SLOT_NUMBER_UNKNOWN : ioc->pci_slot_number;
++      karg.Configuration.bControllerClass = CSMI_SAS_CNTLR_CLASS_HBA;
++      karg.Configuration.bIoBusType = CSMI_SAS_BUS_TYPE_PCI;
++      karg.Configuration.BusAddress.PciAddress.bBusNumber =
++          ioc->pcidev->bus->number;
++      karg.Configuration.BusAddress.PciAddress.bDeviceNumber =
++          PCI_SLOT(ioc->pcidev->devfn);
++      karg.Configuration.BusAddress.PciAddress.bFunctionNumber =
++          PCI_FUNC(ioc->pcidev->devfn);
++      karg.Configuration.BusAddress.PciAddress.bReserved = 0;
++      memcpy( &karg.Configuration.szSerialNumber,ioc->BoardTracerNumber, 16 );
++      karg.Configuration.usMajorRevision = ioc->facts.FWVersion.Struct.Major;
++      karg.Configuration.usMinorRevision = ioc->facts.FWVersion.Struct.Minor;
++      karg.Configuration.usBuildRevision = ioc->facts.FWVersion.Struct.Unit;
++      karg.Configuration.usReleaseRevision = ioc->facts.FWVersion.Struct.Dev;
++      karg.Configuration.usBIOSMajorRevision =
++          (ioc->biosVersion & 0xFF000000) >> 24;
++      karg.Configuration.usBIOSMinorRevision =
++          (ioc->biosVersion & 0x00FF0000) >> 16;
++      karg.Configuration.usBIOSBuildRevision =
++          (ioc->biosVersion & 0x0000FF00) >> 8;
++      karg.Configuration.usBIOSReleaseRevision =
++          (ioc->biosVersion & 0x000000FF);
++      karg.Configuration.uControllerFlags =
++          CSMI_SAS_CNTLR_SAS_HBA | CSMI_SAS_CNTLR_SAS_RAID | 
++          CSMI_SAS_CNTLR_FWD_SUPPORT | CSMI_SAS_CNTLR_FWD_ONLINE | 
++          CSMI_SAS_CNTLR_FWD_SRESET ;
++
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++      /* All Rrom entries will be zero. Skip them. */
++      /* bReserved will also be zeros. */
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++              sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s - "
++              "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get Controller Status command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_cntlr_status(unsigned long arg)
++{
++
++      CSMI_SAS_CNTLR_STATUS_BUFFER  __user *uarg = (void __user *) arg;
++      MPT_ADAPTER             *ioc = NULL;
++      CSMI_SAS_CNTLR_STATUS_BUFFER    karg;
++      int                     iocnum;
++      int                     rc;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s - "
++           "Unable to read in csmi_sas_get_cntlr_status_buffer struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Fill in the data and return the structure to the calling
++       * program
++       */
++
++      rc = mpt_GetIocState(ioc, 1);
++      switch (rc) {
++      case MPI_IOC_STATE_OPERATIONAL:
++              karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_GOOD;
++              karg.Status.uOfflineReason = 0;
++              break;
++
++      case MPI_IOC_STATE_FAULT:
++              karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_FAILED;
++              karg.Status.uOfflineReason = 0;
++              break;
++
++      case MPI_IOC_STATE_RESET:
++      case MPI_IOC_STATE_READY:
++      default:
++              karg.Status.uStatus =  CSMI_SAS_CNTLR_STATUS_OFFLINE;
++              karg.Status.uOfflineReason =
++                  CSMI_SAS_OFFLINE_REASON_INITIALIZING;
++              break;
++      }
++
++      memset(&karg.Status.bReserved, 0, 28);
++
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++              sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s - "
++                  "Unable to write out csmi_sas_get_cntlr_status @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get Phy Info command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_phy_info(unsigned long arg)
++{
++      CSMI_SAS_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_PHY_INFO_BUFFER  karg;
++      MPT_ADAPTER             *ioc = NULL;
++      ConfigExtendedPageHeader_t  hdr;
++      CONFIGPARMS             cfg;
++      SasIOUnitPage0_t        *sasIoUnitPg0;
++      dma_addr_t              sasIoUnitPg0_dma;
++      int                     sasIoUnitPg0_data_sz;
++      SasPhyPage0_t           *sasPhyPg0;
++      dma_addr_t              sasPhyPg0_dma;
++      int                     sasPhyPg0_data_sz;
++      u16                     protocol;
++      int                     iocnum;
++      int                     rc;
++      int                     ii;
++      u64                     SASAddress64;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++      sasIoUnitPg0=NULL;
++      sasPhyPg0=NULL;
++      sasIoUnitPg0_data_sz=0;
++      sasPhyPg0_data_sz=0;
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s - "
++              "Unable to read in csmi_sas_get_phy_info_buffer struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Fill in the data and return the structure to the calling
++       * program
++       */
++      memset( &karg.Information, 0, sizeof(CSMI_SAS_PHY_INFO));
++
++      /* Issue a config request to get the number of phys
++       */
++      hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 0;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
++
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.physAddr = -1;
++      cfg.pageAddr = 0;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              /* Don't check if this failed.  Already in a
++               * failure case.
++               */
++              dctlprintk((
++                  ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: HEADER\n"));
++              dctlprintk((": rc=%x\n",rc));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto sas_get_phy_info_exit;
++      }
++
++      if (hdr.ExtPageLength == 0) {
++              /* Don't check if this failed.  Already in a
++               * failure case.
++               */
++              dctlprintk((": hdr.ExtPageLength == 0\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto sas_get_phy_info_exit;
++      }
++
++      sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
++      rc = -ENOMEM;
++
++      sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
++          sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
++
++      if (!sasIoUnitPg0) {
++              dctlprintk((": pci_alloc_consistent: FAILED\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto sas_get_phy_info_exit;
++      }
++
++      memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
++      cfg.physAddr = sasIoUnitPg0_dma;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++
++              /* Don't check if this failed.  Already in a
++               * failure case.
++               */
++              dctlprintk((
++                  ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: PAGE\n"));
++              dctlprintk((": rc=%x\n",rc));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto sas_get_phy_info_exit;
++      }
++
++
++      /* Number of Phys. */
++      karg.Information.bNumberOfPhys = sasIoUnitPg0->NumPhys;
++
++      /* Fill in information for each phy. */
++      for (ii = 0; ii < karg.Information.bNumberOfPhys; ii++) {
++
++/* EDM : dump IO Unit Page 0 data*/
++              dsasprintk(("---- IO UNIT PAGE 0 ------------\n"));
++              dsasprintk(("Handle=0x%X\n",
++                  le16_to_cpu(sasIoUnitPg0->PhyData[ii].AttachedDeviceHandle)));
++              dsasprintk(("Controller Handle=0x%X\n",
++                  le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle)));
++              dsasprintk(("Port=0x%X\n",
++                  sasIoUnitPg0->PhyData[ii].Port));
++              dsasprintk(("Port Flags=0x%X\n",
++                  sasIoUnitPg0->PhyData[ii].PortFlags));
++              dsasprintk(("PHY Flags=0x%X\n",
++                  sasIoUnitPg0->PhyData[ii].PhyFlags));
++              dsasprintk(("Negotiated Link Rate=0x%X\n",
++                  sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate));
++              dsasprintk(("Controller PHY Device Info=0x%X\n",
++                  le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)));
++              dsasprintk(("DiscoveryStatus=0x%X\n",
++                  le32_to_cpu(sasIoUnitPg0->PhyData[ii].DiscoveryStatus)));
++              dsasprintk(("\n"));
++/* EDM : debug data */
++
++              /* PHY stuff. */
++              karg.Information.Phy[ii].bPortIdentifier =
++                  sasIoUnitPg0->PhyData[ii].Port;
++
++              /* Get the negotiated link rate for the phy. */
++              switch (sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate) {
++
++              case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
++                      karg.Information.Phy[ii].bNegotiatedLinkRate =
++                          CSMI_SAS_PHY_DISABLED;
++                      break;
++
++              case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
++                      karg.Information.Phy[ii].bNegotiatedLinkRate =
++                          CSMI_SAS_LINK_RATE_FAILED;
++                      break;
++
++              case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
++                      break;
++
++              case MPI_SAS_IOUNIT0_RATE_1_5:
++                      karg.Information.Phy[ii].bNegotiatedLinkRate =
++                          CSMI_SAS_LINK_RATE_1_5_GBPS;
++                      break;
++
++              case MPI_SAS_IOUNIT0_RATE_3_0:
++                      karg.Information.Phy[ii].bNegotiatedLinkRate =
++                          CSMI_SAS_LINK_RATE_3_0_GBPS;
++                      break;
++
++              case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
++              default:
++                      karg.Information.Phy[ii].bNegotiatedLinkRate =
++                          CSMI_SAS_LINK_RATE_UNKNOWN;
++                      break;
++              }
++
++              if (sasIoUnitPg0->PhyData[ii].PortFlags &
++                  MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS) {
++                      karg.Information.Phy[ii].bAutoDiscover =
++                          CSMI_SAS_DISCOVER_IN_PROGRESS;
++              } else {
++                      karg.Information.Phy[ii].bAutoDiscover =
++                          CSMI_SAS_DISCOVER_COMPLETE;
++              }
++
++              /* Issue a config request to get
++               * phy information.
++               */
++              hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
++              hdr.ExtPageLength = 0;
++              hdr.PageNumber = 0;
++              hdr.Reserved1 = 0;
++              hdr.Reserved2 = 0;
++              hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++              hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
++
++              cfg.cfghdr.ehdr = &hdr;
++              cfg.physAddr = -1;
++              cfg.pageAddr = ii;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++              cfg.dir = 0;    /* read */
++              cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++              if ((rc = mpt_config(ioc, &cfg)) != 0) {
++                      dctlprintk((
++                          ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
++                      dctlprintk((": rc=%x\n",rc));
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto sas_get_phy_info_exit;
++              }
++
++              if (hdr.ExtPageLength == 0) {
++                      dctlprintk((": pci_alloc_consistent: FAILED\n"));
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto sas_get_phy_info_exit;
++              }
++
++              sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
++              rc = -ENOMEM;
++
++              sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(
++                  ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma);
++
++              if (! sasPhyPg0) {
++                      dctlprintk((": pci_alloc_consistent: FAILED\n"));
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto sas_get_phy_info_exit;
++              }
++
++              memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
++              cfg.physAddr = sasPhyPg0_dma;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++              if ((rc = mpt_config(ioc, &cfg)) != 0) {
++                      dctlprintk((
++                          ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
++                      dctlprintk((": rc=%x\n",rc));
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++                          (u8 *) sasPhyPg0, sasPhyPg0_dma);
++                      goto sas_get_phy_info_exit;
++              }
++
++              le64_to_cpus((u64 *)&sasPhyPg0->SASAddress);
++              memcpy(&SASAddress64, &sasPhyPg0->SASAddress, sizeof(u64));
++
++/* EDM : dump PHY Page 0 data*/
++              dsasprintk(("---- SAS PHY PAGE 0 ------------\n"));
++              dsasprintk(("Handle=0x%X\n",
++                  le16_to_cpu(sasPhyPg0->AttachedDevHandle)));
++              dsasprintk(("SAS Address=0x%llX\n",SASAddress64));
++              dsasprintk(("Attached PHY Identifier=0x%X\n",
++                  sasPhyPg0->AttachedPhyIdentifier));
++              dsasprintk(("Attached Device Info=0x%X\n",
++                  le32_to_cpu(sasPhyPg0->AttachedDeviceInfo)));
++              dsasprintk(("Programmed Link Rate=0x%X\n",
++                  sasPhyPg0->ProgrammedLinkRate));
++              dsasprintk(("Hardware Link Rate=0x%X\n",
++                  ioc->sasPhyInfo[ii].hwLinkRate));
++              dsasprintk(("Change Count=0x%X\n",
++                  sasPhyPg0->ChangeCount));
++              dsasprintk(("PHY Info=0x%X\n",
++                  le32_to_cpu(sasPhyPg0->PhyInfo)));
++              dsasprintk(("\n"));
++/* EDM : debug data */
++
++              /* save the data */
++
++              /* Set Max hardware link rate.
++               * This value is hard coded
++               * because the HW link rate
++               * is currently being
++               * overwritten in FW.
++               */
++
++              /* Set Max hardware link rate. */
++              switch (sasPhyPg0->HwLinkRate &
++                  MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
++
++              case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
++                      karg.Information.Phy[ii].bMaximumLinkRate =
++                          CSMI_SAS_LINK_RATE_1_5_GBPS;
++                      break;
++
++              case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
++                      karg.Information.Phy[ii].bMaximumLinkRate =
++                          CSMI_SAS_LINK_RATE_3_0_GBPS;
++                      break;
++              default:
++                      break;
++              }
++
++              /* Set Max programmed link rate. */
++              switch (sasPhyPg0->ProgrammedLinkRate &
++                  MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
++
++              case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
++                      karg.Information.Phy[ii].bMaximumLinkRate |=
++                          (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
++                      break;
++
++              case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
++                      karg.Information.Phy[ii].bMaximumLinkRate |=
++                          (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
++                      break;
++              default:
++                      break;
++              }
++
++              /* Set Min hardware link rate. */
++              switch (sasPhyPg0->HwLinkRate &
++                  MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
++
++              case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
++                      karg.Information.Phy[ii].bMinimumLinkRate =
++                          CSMI_SAS_LINK_RATE_1_5_GBPS;
++                      break;
++
++              case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
++                      karg.Information.Phy[ii].bMinimumLinkRate =
++                          CSMI_SAS_LINK_RATE_3_0_GBPS;
++                      break;
++              default:
++                      break;
++              }
++
++              /* Set Min programmed link rate. */
++              switch (sasPhyPg0->ProgrammedLinkRate &
++                  MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
++
++              case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
++                      karg.Information.Phy[ii].bMinimumLinkRate |=
++                          (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
++                      break;
++
++              case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
++                      karg.Information.Phy[ii].bMinimumLinkRate |=
++                          (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
++                      break;
++              default:
++                      break;
++              }
++
++              /* Fill in Attached Device
++               * Initiator Port Protocol.
++               * Bits 6:3
++               * More than one bit can be set.
++               */
++              protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x78;
++              karg.Information.Phy[ii].Attached.bInitiatorPortProtocol = 0;
++              if (protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
++                    karg.Information.Phy[ii].Attached.bInitiatorPortProtocol =
++                          CSMI_SAS_PROTOCOL_SSP;
++              if (protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
++                   karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
++                          CSMI_SAS_PROTOCOL_STP;
++              if (protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
++                   karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SMP;
++              if (protocol & MPI_SAS_DEVICE_INFO_SATA_HOST)
++                   karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SATA;
++
++
++              /* Fill in Phy Target Port
++               * Protocol. Bits 10:7
++               * More than one bit can be set.
++               */
++              protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x780;
++              karg.Information.Phy[ii].Attached.bTargetPortProtocol = 0;
++              if (protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET)
++                      karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SSP;
++              if (protocol & MPI_SAS_DEVICE_INFO_STP_TARGET)
++                      karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
++                          CSMI_SAS_PROTOCOL_STP;
++              if (protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET)
++                      karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SMP;
++              if (protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
++                      karg.Information.Phy[ii].Attached.bTargetPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SATA;
++
++
++              /* Fill in Attached device type */
++              switch (le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
++                  MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
++
++              case MPI_SAS_DEVICE_INFO_NO_DEVICE:
++                      karg.Information.Phy[ii].Attached.bDeviceType =
++                          CSMI_SAS_NO_DEVICE_ATTACHED;
++                      break;
++
++              case MPI_SAS_DEVICE_INFO_END_DEVICE:
++                      karg.Information.Phy[ii].Attached.bDeviceType =
++                          CSMI_SAS_END_DEVICE;
++                      break;
++
++              case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
++                      karg.Information.Phy[ii].Attached.bDeviceType =
++                          CSMI_SAS_EDGE_EXPANDER_DEVICE;
++                      break;
++
++              case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
++                      karg.Information.Phy[ii].Attached.bDeviceType =
++                          CSMI_SAS_FANOUT_EXPANDER_DEVICE;
++                      break;
++              }
++
++              /* Identify Info. */
++              switch (le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) &
++                  MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
++
++              case MPI_SAS_DEVICE_INFO_NO_DEVICE:
++                      karg.Information.Phy[ii].Identify.bDeviceType =
++                          CSMI_SAS_NO_DEVICE_ATTACHED;
++                      break;
++
++              case MPI_SAS_DEVICE_INFO_END_DEVICE:
++                      karg.Information.Phy[ii].Identify.bDeviceType =
++                          CSMI_SAS_END_DEVICE;
++                      break;
++
++              case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
++                      karg.Information.Phy[ii].Identify.bDeviceType =
++                          CSMI_SAS_EDGE_EXPANDER_DEVICE;
++                      break;
++
++              case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
++                      karg.Information.Phy[ii].Identify.bDeviceType =
++                          CSMI_SAS_FANOUT_EXPANDER_DEVICE;
++                      break;
++              }
++
++              /* Fill in Phy Initiator Port Protocol. Bits 6:3
++               * More than one bit can be set, fall through cases.
++               */
++              protocol = le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)
++                  & 0x78;
++              karg.Information.Phy[ii].Identify.bInitiatorPortProtocol = 0;
++              if( protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR )
++                   karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SSP;
++              if( protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR )
++                   karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
++                          CSMI_SAS_PROTOCOL_STP;
++              if( protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR )
++                   karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SMP;
++              if( protocol & MPI_SAS_DEVICE_INFO_SATA_HOST )
++                   karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SATA;
++
++              /* Fill in Phy Target Port Protocol. Bits 10:7
++               * More than one bit can be set, fall through cases.
++               */
++              protocol = le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)
++                  & 0x780;
++              karg.Information.Phy[ii].Identify.bTargetPortProtocol = 0;
++              if( protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET )
++                      karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SSP;
++              if( protocol & MPI_SAS_DEVICE_INFO_STP_TARGET )
++                      karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
++                          CSMI_SAS_PROTOCOL_STP;
++              if( protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET )
++                      karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SMP;
++              if( protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE )
++                      karg.Information.Phy[ii].Identify.bTargetPortProtocol |=
++                          CSMI_SAS_PROTOCOL_SATA;
++
++
++              /* Setup Identify SAS Address and Phy Identifier
++               *
++               * Get phy Sas address from device list.
++               * Search the list for the matching
++               * devHandle.
++               */
++
++              /* Setup SAS Address for the Phy */
++              SASAddress64 = reverse_byte_order64((u64 *)&ioc->sasPhyInfo[ii].SASAddress);
++              memcpy(karg.Information.Phy[ii].Identify.bSASAddress,&SASAddress64,
++                  sizeof(u64));
++
++              karg.Information.Phy[ii].Identify.bPhyIdentifier = ii;
++
++              /* Setup SAS Address for the attached device */
++              SASAddress64 = reverse_byte_order64((u64 *)&sasPhyPg0->SASAddress);
++              memcpy(karg.Information.Phy[ii].Attached.bSASAddress,&SASAddress64,
++                  sizeof(u64));
++
++              karg.Information.Phy[ii].Attached.bPhyIdentifier =
++                  sasPhyPg0->AttachedPhyIdentifier;
++
++              pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++                  (u8 *) sasPhyPg0, sasPhyPg0_dma);
++      }
++
++sas_get_phy_info_exit:
++
++      if (sasIoUnitPg0)
++              pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
++                  (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++          sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s - "
++                  "Unable to write out csmi_sas_get_phy_info_buffer @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Set PHY Info command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_set_phy_info(unsigned long arg)
++{
++      CSMI_SAS_SET_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_SET_PHY_INFO_BUFFER     karg;
++      MPT_ADAPTER                     *ioc = NULL;
++      int                             iocnum;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_set_phy_info struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++/* TODO - implement IOCTL here */
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++      dctlprintk((": not implemented\n"));
++
++// cim_set_phy_info_exit:
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++                              sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                      "Unable to write out csmi_sas_set_phy_info @ %p\n",
++                              __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get SCSI Address command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_scsi_address(unsigned long arg)
++{
++      CSMI_SAS_GET_SCSI_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_GET_SCSI_ADDRESS_BUFFER         karg;
++      MPT_ADAPTER             *ioc = NULL;
++      int                     iocnum;
++      sas_device_info_t       *sasDevice;
++      u64                     SASAddress64;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg,
++          sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_get_scsi_address struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++            "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Fill in the data and return the structure to the calling
++       * program
++       */
++
++      /* Copy the SAS address in reverse byte order. */
++      SASAddress64 = reverse_byte_order64((u64 *)&karg.bSASAddress);
++
++      /* Search the list for the matching SAS address. */
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SCSI_ADDRESS;
++      list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++              /* Found the matching device. */
++              if ((memcmp(&sasDevice->SASAddress,
++                  &SASAddress64, sizeof(u64)) != 0))
++                      continue;
++
++              karg.bPathId = sasDevice->Bus;
++              karg.bTargetId = sasDevice->TargetId;
++              karg.bLun = karg.bSASLun[0];
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++              if (((sasDevice->DeviceInfo & 0x00000003) ==
++                      MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) ||
++                      ((sasDevice->DeviceInfo & 0x00000003) ==
++                       MPI_SAS_DEVICE_INFO_EDGE_EXPANDER))
++                      karg.IoctlHeader.ReturnCode =
++                          CSMI_SAS_NOT_AN_END_DEVICE;
++              break;
++      }
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++          sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to write out csmi_sas_get_scsi_address @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get SCSI Address command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_sata_signature(unsigned long arg)
++{
++      CSMI_SAS_SATA_SIGNATURE_BUFFER  __user *uarg = (void __user *) arg;
++      CSMI_SAS_SATA_SIGNATURE_BUFFER   karg;
++      MPT_ADAPTER                     *ioc = NULL;
++      int                             iocnum;
++      int                             rc, jj;
++      ConfigExtendedPageHeader_t      hdr;
++      CONFIGPARMS                     cfg;
++      SasPhyPage0_t                   *sasPhyPg0;
++      dma_addr_t                      sasPhyPg0_dma;
++      int                             sasPhyPg0_data_sz;
++      SasDevicePage1_t                *sasDevicePg1;
++      dma_addr_t                      sasDevicePg1_dma;
++      int                             sasDevicePg1_data_sz;
++      u8                              phyId;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++      sasPhyPg0=NULL;
++      sasPhyPg0_data_sz=0;
++      sasDevicePg1=NULL;
++      sasDevicePg1_data_sz=0;
++
++      if (copy_from_user(&karg, uarg,
++           sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_sata_signature struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++          "%s::%s() @%d - ioc%d not found!\n",
++                   __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      phyId = karg.Signature.bPhyIdentifier;
++      if (phyId >= ioc->numPhys) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
++              dctlprintk((": phyId >= ioc->numPhys\n"));
++              goto cim_sata_signature_exit;
++      }
++
++      /* Default to success.*/
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++      /* Issue a config request to get the devHandle of the attached device
++       */
++
++      /* Issue a config request to get phy information. */
++      hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 0;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
++
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.physAddr = -1;
++      cfg.pageAddr = phyId;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              /* Don't check if this failed.  Already in a
++               * failure case.
++               */
++              dctlprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
++              dctlprintk((": rc=%x\n",rc));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sata_signature_exit;
++      }
++
++      if (hdr.ExtPageLength == 0) {
++              /* Don't check if this failed.  Already in a
++               * failure case.
++               */
++              dctlprintk((": hdr.ExtPageLength == 0\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sata_signature_exit;
++      }
++
++
++      sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
++      rc = -ENOMEM;
++
++      sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(ioc->pcidev,
++          sasPhyPg0_data_sz, &sasPhyPg0_dma);
++
++      if (! sasPhyPg0) {
++              dctlprintk((": pci_alloc_consistent: FAILED\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sata_signature_exit;
++      }
++
++      memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
++      cfg.physAddr = sasPhyPg0_dma;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              /* Don't check if this failed.  Already in a
++               * failure case.
++               */
++              dctlprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
++              dctlprintk((": rc=%x\n",rc));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sata_signature_exit;
++      }
++
++      /* Make sure a SATA device is attached. */
++      if ((le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
++          MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0) {
++              dctlprintk((": NOT A SATA DEVICE\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SATA_DEVICE;
++              goto cim_sata_signature_exit;
++      }
++
++      /* Get device page 1 for FIS  signature. */
++      hdr.PageVersion = MPI_SASDEVICE1_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 1 /* page number 1 */;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
++
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.physAddr = -1;
++
++      cfg.pageAddr = ((MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
++          MPI_SAS_DEVICE_PGAD_FORM_SHIFT) |
++          le16_to_cpu(sasPhyPg0->AttachedDevHandle));
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              dctlprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: HEADER\n"));
++              dctlprintk((": rc=%x\n",rc));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sata_signature_exit;
++      }
++
++      if (hdr.ExtPageLength == 0) {
++              dctlprintk((": hdr.ExtPageLength == 0\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sata_signature_exit;
++      }
++
++      sasDevicePg1_data_sz = hdr.ExtPageLength * 4;
++      rc = -ENOMEM;
++
++      sasDevicePg1 = (SasDevicePage1_t *) pci_alloc_consistent
++          (ioc->pcidev, sasDevicePg1_data_sz, &sasDevicePg1_dma);
++
++      if (! sasDevicePg1) {
++              dctlprintk((": pci_alloc_consistent: FAILED\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sata_signature_exit;
++      }
++
++      memset((u8 *)sasDevicePg1, 0, sasDevicePg1_data_sz);
++      cfg.physAddr = sasDevicePg1_dma;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              dctlprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: PAGE\n"));
++              dctlprintk((": rc=%x\n",rc));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sata_signature_exit;
++      }
++
++/* EDM : dump Device Page 1 data*/
++      dsasprintk(("---- SAS DEVICE PAGE 1 ---------\n"));
++      dsasprintk(("Handle=0x%x\n",sasDevicePg1->DevHandle));
++      dsasprintk(("SAS Address="));
++      for(jj=0;jj<8;jj++)
++              dsasprintk(("%02x ",
++              ((u8 *)&sasDevicePg1->SASAddress)[jj]));
++      dsasprintk(("\n"));
++      dsasprintk(("Target ID=0x%x\n",sasDevicePg1->TargetID));
++      dsasprintk(("Bus=0x%x\n",sasDevicePg1->Bus));
++      dsasprintk(("Initial Reg Device FIS="));
++      for(jj=0;jj<20;jj++)
++              dsasprintk(("%02x ",
++              ((u8 *)&sasDevicePg1->InitialRegDeviceFIS)[jj]));
++      dsasprintk(("\n\n"));
++/* EDM : debug data */
++
++      memcpy(karg.Signature.bSignatureFIS,
++              sasDevicePg1->InitialRegDeviceFIS,20);
++
++cim_sata_signature_exit:
++
++      if (sasPhyPg0)
++              pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++                  (u8 *) sasPhyPg0, sasPhyPg0_dma);
++
++      if (sasDevicePg1)
++              pci_free_consistent(ioc->pcidev, sasDevicePg1_data_sz,
++                  (u8 *) sasDevicePg1, sasDevicePg1_dma);
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++          sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to write out csmi_sas_sata_signature @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get SCSI Address command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_device_address(unsigned long arg)
++{
++      CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER       karg;
++      MPT_ADAPTER             *ioc = NULL;
++      int                     iocnum;
++      sas_device_info_t       *sasDevice;
++      u64                     SASAddress64;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg,
++          sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++         "Unable to read in csmi_sas_get_device_address_buffer struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++          "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Fill in the data and return the structure to the calling
++       * program
++       */
++
++      /* Search the list for the matching SAS address. */
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_DEVICE_ADDRESS;
++      list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++              /* Find the matching device. */
++              if ((karg.bPathId == sasDevice->Bus) &&
++                      (karg.bTargetId == sasDevice->TargetId)) {
++
++                      SASAddress64 = reverse_byte_order64(&sasDevice->SASAddress);
++                      memcpy(&karg.bSASAddress,&SASAddress64,sizeof(u64));
++                      karg.bSASLun[0] = karg.bLun;
++                      memset(karg.bSASLun, 0, sizeof(karg.bSASLun));
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++                      break;
++              } else
++                      /* Keep looking. */
++                      continue;
++      }
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++          sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++              "Unable to write out csmi_sas_get_device_address_buffer @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI Sas Get Link Errors command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_link_errors(unsigned long arg)
++{
++      CSMI_SAS_LINK_ERRORS_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_LINK_ERRORS_BUFFER      karg;
++      MPT_ADAPTER                     *ioc = NULL;
++      MPT_FRAME_HDR                   *mf = NULL;
++      MPIHeader_t                     *mpi_hdr;
++      int                             iocnum;
++      int                             rc,ii;
++      ConfigExtendedPageHeader_t      hdr;
++      CONFIGPARMS                     cfg;
++      SasPhyPage1_t                   *sasPhyPage1;
++      dma_addr_t                      sasPhyPage1_dma;
++      int                             sasPhyPage1_data_sz;
++      SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
++      SasIoUnitControlReply_t         *sasIoUnitCntrReply;
++      u8                              phyId;
++      int                             wait_timeout;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++      sasPhyPage1=NULL;
++      sasPhyPage1_data_sz=0;
++
++      if (copy_from_user(&karg, uarg,
++           sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in mptctl_csmi_sas_get_link_errors struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++          "%s::%s() @%d - ioc%d not found!\n",
++                   __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      phyId = karg.Information.bPhyIdentifier;
++      if (phyId >= ioc->numPhys) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
++              dctlprintk((": phyId >= ioc->numPhys\n"));
++              goto cim_get_link_errors_exit;
++      }
++
++      /* Default to success.*/
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++      /* Issue a config request to get the devHandle of the attached device
++       */
++
++      /* Issue a config request to get phy information. */
++      hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 1 /* page number 1*/;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
++
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.physAddr = -1;
++      cfg.pageAddr = phyId;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              /* Don't check if this failed.  Already in a
++               * failure case.
++               */
++              dctlprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: HEADER\n"));
++              dctlprintk((": rc=%x\n",rc));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_link_errors_exit;
++      }
++
++      if (hdr.ExtPageLength == 0) {
++              /* Don't check if this failed.  Already in a
++               * failure case.
++               */
++              dctlprintk((": hdr.ExtPageLength == 0\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_link_errors_exit;
++      }
++
++
++      sasPhyPage1_data_sz = hdr.ExtPageLength * 4;
++      rc = -ENOMEM;
++
++      sasPhyPage1 = (SasPhyPage1_t *) pci_alloc_consistent(ioc->pcidev,
++          sasPhyPage1_data_sz, &sasPhyPage1_dma);
++
++      if (! sasPhyPage1) {
++              dctlprintk((": pci_alloc_consistent: FAILED\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_link_errors_exit;
++      }
++
++      memset((u8 *)sasPhyPage1, 0, sasPhyPage1_data_sz);
++      cfg.physAddr = sasPhyPage1_dma;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              /* Don't check if this failed.  Already in a
++               * failure case.
++               */
++              dctlprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: PAGE\n"));
++              dctlprintk((": rc=%x\n",rc));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_link_errors_exit;
++      }
++
++/* EDM : dump PHY Page 1 data*/
++      dsasprintk(("---- SAS PHY PAGE 1 ------------\n"));
++      dsasprintk(("Invalid Dword Count=0x%x\n",
++          sasPhyPage1->InvalidDwordCount));
++      dsasprintk(("Running Disparity Error Count=0x%x\n",
++          sasPhyPage1->RunningDisparityErrorCount));
++      dsasprintk(("Loss Dword Synch Count=0x%x\n",
++          sasPhyPage1->LossDwordSynchCount));
++      dsasprintk(("PHY Reset Problem Count=0x%x\n",
++          sasPhyPage1->PhyResetProblemCount));
++      dsasprintk(("\n\n"));
++/* EDM : debug data */
++
++      karg.Information.uInvalidDwordCount =
++              le32_to_cpu(sasPhyPage1->InvalidDwordCount);
++      karg.Information.uRunningDisparityErrorCount =
++              le32_to_cpu(sasPhyPage1->RunningDisparityErrorCount);
++      karg.Information.uLossOfDwordSyncCount =
++              le32_to_cpu(sasPhyPage1->LossDwordSynchCount);
++      karg.Information.uPhyResetProblemCount =
++              le32_to_cpu(sasPhyPage1->PhyResetProblemCount);
++
++      if (karg.Information.bResetCounts ==
++          CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS ) {
++              goto cim_get_link_errors_exit;
++      }
++
++      /* Clear Error log
++       *
++       * Issue IOUNIT Control Reqeust Message
++       */
++
++      /* Get a MF for this command.
++       */
++      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++              dctlprintk((": no msg frames!\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_link_errors_exit;
++        }
++
++      mpi_hdr = (MPIHeader_t *) mf;
++      sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
++      memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
++      sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
++      sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
++      sasIoUnitCntrReq->PhyNum = phyId;
++      sasIoUnitCntrReq->Operation = MPI_SAS_OP_PHY_CLEAR_ERROR_LOG;
++
++      ioc->ioctl->wait_done = 0;
++      mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++      /* Now wait for the command to complete */
++      wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++      ii = wait_event_timeout(mptctl_wait,
++           ioc->ioctl->wait_done == 1,
++           HZ*wait_timeout);
++
++      if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++      /* Now we need to reset the board */
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              mpt_free_msg_frame(ioc, mf);
++              mptctl_timeout_expired(ioc->ioctl);
++              goto cim_get_link_errors_exit;
++      }
++
++      /* process the completed Reply Message Frame */
++      if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
++
++              sasIoUnitCntrReply =
++                  (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame;
++
++              if ( le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
++                      dctlprintk((": SAS IO Unit Control: "));
++                      dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n",
++                          sasIoUnitCntrReply->IOCStatus,
++                          sasIoUnitCntrReply->IOCLogInfo));
++              }
++      }
++
++cim_get_link_errors_exit:
++
++      ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_TM_FAILED |
++          MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++          MPT_IOCTL_STATUS_RF_VALID);
++
++      if (sasPhyPage1)
++              pci_free_consistent(ioc->pcidev, sasPhyPage1_data_sz,
++                  (u8 *) sasPhyPage1, sasPhyPage1_dma);
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++          sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to write out mptctl_csmi_sas_get_link_errors @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS SMP Passthru command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_smp_passthru(unsigned long arg)
++{
++      CSMI_SAS_SMP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
++      MPT_ADAPTER                     *ioc;
++      CSMI_SAS_SMP_PASSTHRU_BUFFER     karg;
++      pSmpPassthroughRequest_t        smpReq;
++      pSmpPassthroughReply_t          smpReply;
++      MPT_FRAME_HDR                   *mf = NULL;
++      MPIHeader_t                     *mpi_hdr;
++      char                            *psge;
++      int                             iocnum, flagsLength,ii;
++      u8                              index;
++      void *                          request_data;
++      dma_addr_t                      request_data_dma;
++      u32                             request_data_sz;
++      void *                          response_data;
++      dma_addr_t                      response_data_dma;
++      u32                             response_data_sz;
++      u16                             ioc_stat;
++      int                             wait_timeout;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_smp_passthru struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      request_data = NULL;
++      response_data = NULL;
++      response_data_sz = sizeof(CSMI_SAS_SMP_RESPONSE);
++      request_data_sz  = karg.Parameters.uRequestLength;
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Make sure the adapter is not being reset. */
++      if (!ioc->ioctl) {
++              printk(KERN_ERR "%s@%d::%s - "
++                  "No memory available during driver init.\n",
++                  __FILE__, __LINE__,__FUNCTION__);
++              return -ENOMEM;
++      } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
++              printk(KERN_ERR "%s@%d::%s - "
++                  "Busy with IOC Reset \n",
++                  __FILE__, __LINE__,__FUNCTION__);
++              return -EBUSY;
++      }
++
++      /* Default to success.*/
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++      /* Do some error checking on the request. */
++      if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
++              goto cim_smp_passthru_exit;
++      }
++
++      if ((request_data_sz > 0xFFFF) || (!request_data_sz)) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_smp_passthru_exit;
++      }
++
++      /* Get a free request frame and save the message context.
++       */
++      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++              dctlprintk((": no msg frames!\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_smp_passthru_exit;
++        }
++
++      mpi_hdr = (MPIHeader_t *) mf;
++      smpReq = (pSmpPassthroughRequest_t ) mf;
++
++      memset(smpReq,0,ioc->req_sz);
++
++      /* Fill in smp request. */
++      smpReq->PhysicalPort = karg.Parameters.bPortIdentifier;
++      smpReq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
++      smpReq->RequestDataLength = cpu_to_le16(request_data_sz);
++      smpReq->ConnectionRate = karg.Parameters.bConnectionRate;
++      smpReq->MsgContext = mpi_hdr->MsgContext;
++      for ( index = 0; index < 8; index++ ) {
++              ((u8*)&smpReq->SASAddress)[7 - index] =
++                  karg.Parameters.bDestinationSASAddress[index];
++      }
++      smpReq->Reserved2 = 0;
++      smpReq->Reserved3 = 0;
++
++      /*
++       * Prepare the necessary pointers to run
++       * through the SGL generation
++       */
++
++      psge = (char *)&smpReq->SGL;
++
++      /* setup the *Request* payload SGE */
++      flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++              MPI_SGE_FLAGS_SYSTEM_ADDRESS |
++              MPI_SGE_FLAGS_32_BIT_ADDRESSING |
++              MPI_SGE_FLAGS_HOST_TO_IOC |
++              MPI_SGE_FLAGS_END_OF_BUFFER;
++
++      if (sizeof(dma_addr_t) == sizeof(u64)) {
++              flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
++      }
++      flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
++      flagsLength |= request_data_sz;
++
++      request_data = pci_alloc_consistent(
++          ioc->pcidev, request_data_sz, &request_data_dma);
++
++      if (!request_data) {
++              dctlprintk((": pci_alloc_consistent: FAILED\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              mpt_free_msg_frame(ioc, mf);
++              goto cim_smp_passthru_exit;
++      }
++
++      mpt_add_sge(psge, flagsLength, request_data_dma);
++      psge += (sizeof(u32) + sizeof(dma_addr_t));
++
++      memcpy(request_data,&karg.Parameters.Request,request_data_sz);
++
++      /* setup the *Response* payload SGE */
++      response_data = pci_alloc_consistent(
++          ioc->pcidev, response_data_sz, &response_data_dma);
++
++      if (!response_data) {
++              dctlprintk((": pci_alloc_consistent: FAILED\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              mpt_free_msg_frame(ioc, mf);
++              goto cim_smp_passthru_exit;
++      }
++
++      flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++              MPI_SGE_FLAGS_SYSTEM_ADDRESS |
++              MPI_SGE_FLAGS_32_BIT_ADDRESSING |
++              MPI_SGE_FLAGS_IOC_TO_HOST |
++              MPI_SGE_FLAGS_END_OF_BUFFER;
++
++      if (sizeof(dma_addr_t) == sizeof(u64)) {
++              flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
++      }
++
++      flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
++      flagsLength |= response_data_sz;
++
++      mpt_add_sge(psge, flagsLength, response_data_dma);
++
++      /* The request is complete. Set the timer parameters
++       * and issue the request.
++       */
++      ioc->ioctl->wait_done = 0;
++      mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++      /* Now wait for the command to complete */
++      wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++      ii = wait_event_timeout(mptctl_wait,
++           ioc->ioctl->wait_done == 1,
++           HZ*wait_timeout);
++
++      if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++      /* Now we need to reset the board */
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              mpt_free_msg_frame(ioc, mf);
++              mptctl_timeout_expired(ioc->ioctl);
++              goto cim_smp_passthru_exit;
++      }
++
++      if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) {
++              dctlprintk((": SMP Passthru: oh no, there is no reply!!"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_smp_passthru_exit;
++      }
++
++      /* process the completed Reply Message Frame */
++      smpReply = (pSmpPassthroughReply_t )ioc->ioctl->ReplyFrame;
++      ioc_stat = le16_to_cpu(smpReply->IOCStatus) & MPI_IOCSTATUS_MASK;
++
++      if ((ioc_stat != MPI_IOCSTATUS_SUCCESS) &&
++          (ioc_stat != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              dctlprintk((": SMP Passthru: "));
++              dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
++                  smpReply->IOCStatus,
++                  smpReply->IOCLogInfo,
++                  smpReply->SASStatus));
++              goto cim_smp_passthru_exit;
++      }
++
++      karg.Parameters.bConnectionStatus =
++          map_sas_status_to_csmi(smpReply->SASStatus);
++
++
++      if (le16_to_cpu(smpReply->ResponseDataLength)) {
++              karg.Parameters.uResponseBytes = le16_to_cpu(smpReply->ResponseDataLength);
++              memcpy(&karg.Parameters.Response,
++                  response_data, le16_to_cpu(smpReply->ResponseDataLength));
++      }
++
++cim_smp_passthru_exit:
++
++      ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++          MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++          MPT_IOCTL_STATUS_RF_VALID);
++
++      if (request_data)
++              pci_free_consistent(ioc->pcidev, request_data_sz,
++                  (u8 *)request_data, request_data_dma);
++
++      if (response_data)
++              pci_free_consistent(ioc->pcidev, response_data_sz,
++                  (u8 *)response_data, response_data_dma);
++
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++                              sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                      "Unable to write out csmi_sas_smp_passthru @ %p\n",
++                              __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS SSP Passthru command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int mptctl_csmi_sas_ssp_passthru(unsigned long arg)
++{
++      CSMI_SAS_SSP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_SSP_PASSTHRU_BUFFER     karg;
++      MPT_ADAPTER                     *ioc = NULL;
++      pSCSIIORequest_t                pScsiRequest;
++      pSCSIIOReply_t                  pScsiReply;
++      MPT_FRAME_HDR                   *mf = NULL;
++      MPIHeader_t                     *mpi_hdr;
++      int                             iocnum,ii;
++      u32                             data_sz;
++      u64                             SASAddress64;
++      sas_device_info_t               *sasDevice;
++      u16                             req_idx;
++      char                            *psge;
++      int                             flagsLength;
++      void *                          request_data;
++      dma_addr_t                      request_data_dma;
++      u32                             request_data_sz;
++      u8                              found;
++      u16                             ioc_stat;
++      u8                              volume_id;
++      u8                              volume_bus;
++      u8                              quiese_io_flag=0;
++      u8                              bus;
++      u8                              target;
++      int                             wait_timeout;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      request_data=NULL;
++      request_data_sz = karg.Parameters.uDataLength;
++      bus=0;
++      target=0;
++      volume_id=0;
++      volume_bus=0;
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s()"
++                  " @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Default to success.
++       */
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++      /* Neither a phy nor a port has been selected.
++       */
++      if ((karg.Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
++              (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
++              dctlprintk((KERN_ERR
++                  "%s::%s()"
++                  " @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
++                  __FILE__, __FUNCTION__, __LINE__));
++              goto cim_ssp_passthru_exit;
++      }
++
++      /* A phy has been selected. Verify that it's valid.
++       */
++      if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
++
++              /* Is the phy in range? */
++              if (karg.Parameters.bPhyIdentifier >= ioc->numPhys) {
++                      karg.IoctlHeader.ReturnCode =
++                          CSMI_SAS_PHY_DOES_NOT_EXIST;
++                      goto cim_ssp_passthru_exit;
++              }
++      }
++
++      /* some checks of the incoming frame
++       */
++      if (request_data_sz > 0xFFFF) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              dctlprintk((KERN_ERR
++                  "%s::%s()"
++                  " @%d - uDataLength > 0xFFFF!\n",
++                  __FILE__, __FUNCTION__, __LINE__));
++              goto cim_ssp_passthru_exit;
++      }
++
++      data_sz = sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER) -
++          sizeof(IOCTL_HEADER) - sizeof(u8*) +
++          request_data_sz;
++
++      if ( data_sz > karg.IoctlHeader.Length ) {
++              karg.IoctlHeader.ReturnCode =
++                  CSMI_SAS_STATUS_INVALID_PARAMETER;
++              dctlprintk((KERN_ERR
++                  "%s::%s()"
++                  " @%d - expected datalen incorrect!\n",
++                  __FILE__, __FUNCTION__, __LINE__));
++              goto cim_ssp_passthru_exit;
++      }
++
++      /* we will use SAS address to resolve the scsi adddressing
++       */
++      memcpy(&SASAddress64,karg.Parameters.bDestinationSASAddress,
++          sizeof(u64));
++      SASAddress64 = reverse_byte_order64(&SASAddress64);
++
++      /* Search the list for the matching SAS address.
++       */
++      found = FALSE;
++      list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++              /* Find the matching device.
++               */
++              if (sasDevice->SASAddress != SASAddress64)
++                      continue;
++
++              found = TRUE;
++              bus = sasDevice->Bus;
++              target = sasDevice->TargetId;
++              break;
++      }
++
++      /* Invalid SAS address
++       */
++      if (found == FALSE) {
++              karg.IoctlHeader.ReturnCode =
++                  CSMI_SAS_STATUS_INVALID_PARAMETER;
++              dctlprintk((KERN_ERR
++                  "%s::%s()"
++                  " @%d - couldn't find associated SASAddress!\n",
++                  __FILE__, __FUNCTION__, __LINE__));
++              goto cim_ssp_passthru_exit;
++      }
++
++      if(karg.Parameters.bAdditionalCDBLength) {
++      /* TODO - SCSI IO (32) Request Message support
++       */
++              dctlprintk((": greater than 16-byte cdb is not supported!\n"));
++              karg.IoctlHeader.ReturnCode =
++                  CSMI_SAS_STATUS_INVALID_PARAMETER;
++              goto cim_ssp_passthru_exit;
++      }
++
++      /* see if this is for raid phy disk */
++      if (ioc->raid_data.isRaid && ioc->raid_data.pIocPg3) {
++              for (ii = 0; (ii<ioc->raid_data.pIocPg3->NumPhysDisks &&
++                  quiese_io_flag==0); ii++) {
++                      if (target == ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskID) {
++                              target = ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskNum;
++                              quiese_io_flag=1;
++                      }
++              }
++      }
++#ifdef QUIESE_IO
++      /* if RAID Volume, then quiesce io to phys disk*/
++      if (quiese_io_flag==1) {
++              if (mptctl_raid_get_volume_id(ioc, target,
++                  &volume_id, &volume_bus) != 0) {
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto cim_ssp_passthru_exit;
++              }
++              mptctl_do_raid(ioc,
++                  MPI_RAID_ACTION_QUIESCE_PHYS_IO,
++                  target, volume_bus, volume_id, NULL);
++      }
++#endif
++      /* Get a free request frame and save the message context.
++       */
++      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++              dctlprintk((": no msg frames!\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_ssp_passthru_exit;
++        }
++
++      mpi_hdr = (MPIHeader_t *) mf;
++      pScsiRequest = (pSCSIIORequest_t) mf;
++      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
++
++      memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
++
++      /* Fill in SCSI IO (16) request.
++       */
++
++      pScsiRequest->Function = (quiese_io_flag==1) ?
++          MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : MPI_FUNCTION_SCSI_IO_REQUEST;
++      pScsiRequest->TargetID = target;
++      pScsiRequest->Bus = bus;
++      memcpy(pScsiRequest->LUN,karg.Parameters.bLun,8);
++      pScsiRequest->CDBLength = karg.Parameters.bCDBLength;
++      pScsiRequest->DataLength = cpu_to_le16(request_data_sz);
++      pScsiRequest->MsgContext = mpi_hdr->MsgContext;
++      memcpy(pScsiRequest->CDB,karg.Parameters.bCDB,
++          pScsiRequest->CDBLength);
++
++      /* direction
++       */
++      if (karg.Parameters.uFlags & CSMI_SAS_SSP_READ) {
++              pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
++      } else if (karg.Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
++              pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_WRITE);
++      } else if ((karg.Parameters.uFlags & CSMI_SAS_SSP_UNSPECIFIED) &&
++          (!karg.Parameters.uDataLength)) {
++              /* no data transfer
++               */
++              pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_NODATATRANSFER);
++      } else {
++              /* no direction specified
++               */
++              pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
++              pScsiRequest->MsgFlags =
++                  MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR;
++      }
++
++      /* task attributes
++       */
++      if((karg.Parameters.uFlags && 0xFF) == 0) {
++              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
++      } else if (karg.Parameters.uFlags &
++          CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE) {
++              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_HEADOFQ);
++      } else if (karg.Parameters.uFlags &
++          CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED) {
++              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ORDEREDQ);
++      } else if (karg.Parameters.uFlags &
++          CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA) {
++              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ACAQ);
++      } else {
++              pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_UNTAGGED);
++      }
++
++      /* setup sense
++       */
++      pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
++      pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
++          (req_idx * MPT_SENSE_BUFFER_ALLOC));
++
++      /* setup databuffer sg, assuming we fit everything one contiguous buffer
++       */
++      psge = (char *)&pScsiRequest->SGL;
++
++      if (karg.Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
++              flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
++      } else if (karg.Parameters.uFlags & CSMI_SAS_SSP_READ) {
++              flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
++      }else {
++              flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++                              MPI_SGE_FLAGS_DIRECTION |
++                              mpt_addr_size() )
++                              << MPI_SGE_FLAGS_SHIFT;
++      }
++      flagsLength |= request_data_sz;
++
++      if ( request_data_sz > 0) {
++              request_data = pci_alloc_consistent(
++                  ioc->pcidev, request_data_sz, &request_data_dma);
++
++              if (request_data == NULL) {
++                      dctlprintk((": pci_alloc_consistent: FAILED request_data_sz=%d\n", request_data_sz));
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      mpt_free_msg_frame(ioc, mf);
++                      goto cim_ssp_passthru_exit;
++              }
++
++              mpt_add_sge(psge, flagsLength, request_data_dma);
++
++              if (karg.Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
++
++                      if (copy_from_user(request_data,
++                          karg.bDataBuffer,
++                          request_data_sz)) {
++                              printk(KERN_ERR
++                              "%s@%d::%s - Unable "
++                                  "to read user data "
++                                  "struct @ %p\n",
++                                  __FILE__, __LINE__,__FUNCTION__,
++                                  (void*)karg.bDataBuffer);
++                              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                              mpt_free_msg_frame(ioc, mf);
++                              goto cim_ssp_passthru_exit;
++                      }
++              }
++      } else {
++              mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
++      }
++
++      /* The request is complete. Set the timer parameters
++       * and issue the request.
++       */
++      ioc->ioctl->wait_done = 0;
++      mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++      /* Now wait for the command to complete */
++      wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++      ii = wait_event_timeout(mptctl_wait,
++           ioc->ioctl->wait_done == 1,
++           HZ*wait_timeout);
++
++      if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++      /* Now we need to reset the board */
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              mpt_free_msg_frame(ioc, mf);
++              mptctl_timeout_expired(ioc->ioctl);
++              goto cim_ssp_passthru_exit;
++      }
++
++      memset(&karg.Status,0,sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
++      karg.Status.bConnectionStatus = CSMI_SAS_OPEN_ACCEPT;
++      karg.Status.bDataPresent = CSMI_SAS_SSP_NO_DATA_PRESENT;
++      karg.Status.bStatus = GOOD;
++      karg.Status.bResponseLength[0] = 0;
++      karg.Status.bResponseLength[1] = 0;
++      karg.Status.uDataBytes = request_data_sz;
++
++      /* process the completed Reply Message Frame */
++      if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
++
++              pScsiReply = (pSCSIIOReply_t ) ioc->ioctl->ReplyFrame;
++              karg.Status.bStatus = pScsiReply->SCSIStatus;
++              karg.Status.uDataBytes = min(le32_to_cpu(pScsiReply->TransferCount),
++                  request_data_sz);
++              ioc_stat = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
++
++              if (pScsiReply->SCSIState ==
++                  MPI_SCSI_STATE_AUTOSENSE_VALID) {
++                      karg.Status.bConnectionStatus =
++                          CSMI_SAS_SSP_SENSE_DATA_PRESENT;
++                      karg.Status.bResponseLength[0] =
++                              (u8)le32_to_cpu(pScsiReply->SenseCount) & 0xFF;
++                      memcpy(karg.Status.bResponse,
++                          ioc->ioctl->sense, le32_to_cpu(pScsiReply->SenseCount));
++              } else if(pScsiReply->SCSIState ==
++                  MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
++                      karg.Status.bDataPresent =
++                          CSMI_SAS_SSP_RESPONSE_DATA_PRESENT;
++                      karg.Status.bResponseLength[0] =
++                              sizeof(pScsiReply->ResponseInfo);
++                      for (ii=0;ii<sizeof(pScsiReply->ResponseInfo);ii++) {
++                              karg.Status.bResponse[ii] =
++                              ((u8*)&pScsiReply->ResponseInfo)[
++                                  (sizeof(pScsiReply->ResponseInfo)-1)-ii];
++                      }
++              } else if ((ioc_stat != MPI_IOCSTATUS_SUCCESS) &&
++                  (ioc_stat !=  MPI_IOCSTATUS_SCSI_RECOVERED_ERROR) &&
++                  (ioc_stat != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      dctlprintk((": SCSI IO : "));
++                      dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n",
++                          pScsiReply->IOCStatus,
++                          pScsiReply->IOCLogInfo));
++              }
++      }
++
++      if ((karg.Status.uDataBytes) && (request_data) &&
++          (karg.Parameters.uFlags & CSMI_SAS_SSP_READ)) {
++              if (copy_to_user((char *)uarg->bDataBuffer,
++                  request_data, karg.Status.uDataBytes)) {
++                      printk(KERN_ERR "%s@%d::%s - "
++                          "Unable to write data to user %p\n",
++                          __FILE__, __LINE__,__FUNCTION__,
++                          (void*)karg.bDataBuffer);
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              }
++      }
++
++cim_ssp_passthru_exit:
++
++      ioc->ioctl->status &= ~(  MPT_IOCTL_STATUS_TM_FAILED |
++          MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++          MPT_IOCTL_STATUS_RF_VALID);
++
++      if (request_data)
++              pci_free_consistent(ioc->pcidev, request_data_sz,
++                  (u8 *)request_data, request_data_dma);
++
++#ifdef QUIESE_IO
++      if (quiese_io_flag) {
++              mptctl_do_raid(ioc,
++                  MPI_RAID_ACTION_ENABLE_PHYS_IO,
++                  target, volume_bus, volume_id, NULL);
++      }
++#endif
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++          offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                      "Unable to write out csmi_sas_ssp_passthru @ %p\n",
++                              __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS STP Passthru command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_stp_passthru(unsigned long arg)
++{
++      CSMI_SAS_STP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_STP_PASSTHRU_BUFFER     karg;
++      MPT_ADAPTER                     *ioc = NULL;
++      pSataPassthroughRequest_t       pSataRequest;
++      pSataPassthroughReply_t         pSataReply;
++      MPT_FRAME_HDR                   *mf = NULL;
++      MPIHeader_t                     *mpi_hdr;
++      int                             iocnum,ii;
++      u32                             data_sz;
++      u64                             SASAddress64;
++      sas_device_info_t               *sasDevice=NULL;
++      u16                             req_idx;
++      char                            *psge;
++      int                             flagsLength;
++      void *                          request_data;
++      dma_addr_t                      request_data_dma;
++      u32                             request_data_sz;
++      u8                              found;
++      u8                              bus;
++      u8                              target;
++      u8                              volume_id;
++      u8                              volume_bus;
++#ifdef QUIESE_IO
++      u8                              quiese_io_flag=0;
++      u8                              phys_disk_num=0;
++#endif
++      int                             wait_timeout;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      request_data=NULL;
++      request_data_sz = karg.Parameters.uDataLength;
++      volume_id=0;
++      volume_bus=0;
++      bus=0;
++      target=0;
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Default to success.
++       */
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++      /* Neither a phy nor a port has been selected.
++       */
++      if ((karg.Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
++              (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
++                  __FILE__,__FUNCTION__, __LINE__));
++              goto cim_stp_passthru_exit;
++      }
++
++      /* A phy has been selected. Verify that it's valid.
++       */
++      if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
++
++              /* Is the phy in range? */
++              if (karg.Parameters.bPhyIdentifier >= ioc->numPhys) {
++                      karg.IoctlHeader.ReturnCode =
++                          CSMI_SAS_PHY_DOES_NOT_EXIST;
++                      goto cim_stp_passthru_exit;
++              }
++      }
++
++      /* some checks of the incoming frame
++       */
++      if (request_data_sz > 0xFFFF) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - uDataLength > 0xFFFF!\n",
++                  __FILE__, __FUNCTION__, __LINE__));
++              goto cim_stp_passthru_exit;
++      }
++
++      data_sz = sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) -
++          sizeof(IOCTL_HEADER) - sizeof(u8*) +
++          request_data_sz;
++
++      if ( data_sz > karg.IoctlHeader.Length ) {
++              karg.IoctlHeader.ReturnCode =
++                  CSMI_SAS_STATUS_INVALID_PARAMETER;
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - expected datalen incorrect!\n",
++                  __FILE__, __FUNCTION__,__LINE__));
++              goto cim_stp_passthru_exit;
++      }
++
++      /* we will use SAS address to resolve the scsi adddressing
++       */
++      memcpy(&SASAddress64,karg.Parameters.bDestinationSASAddress,
++          sizeof(u64));
++      SASAddress64 = reverse_byte_order64(&SASAddress64);
++
++      /* Search the list for the matching SAS address.
++       */
++      found = FALSE;
++      list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++              /* Find the matching device.
++               */
++              if (sasDevice->SASAddress != SASAddress64)
++                      continue;
++
++              found = TRUE;
++              bus = sasDevice->Bus;
++              target = sasDevice->TargetId;;
++              break;
++      }
++
++      /* Invalid SAS address
++       */
++      if (found == FALSE) {
++              karg.IoctlHeader.ReturnCode =
++                  CSMI_SAS_STATUS_INVALID_PARAMETER;
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - couldn't find associated SASAddress!\n",
++                  __FILE__, __FUNCTION__, __LINE__));
++              goto cim_stp_passthru_exit;
++      }
++
++      /* check that this is an STP or SATA target device
++       */
++      if ( !(sasDevice->DeviceInfo & MPI_SAS_DEVICE_INFO_STP_TARGET ) &&
++           !(sasDevice->DeviceInfo & MPI_SAS_DEVICE_INFO_SATA_DEVICE )) {
++              karg.IoctlHeader.ReturnCode =
++                  CSMI_SAS_STATUS_INVALID_PARAMETER;
++              goto cim_stp_passthru_exit;
++      }
++
++#ifdef QUIESE_IO
++      /* see if this is for raid phy disk */
++      if (ioc->raid_data.isRaid && ioc->raid_data.pIocPg3) {
++              for (ii = 0; (ii<ioc->raid_data.pIocPg3->NumPhysDisks &&
++                  quiese_io_flag==0); ii++)
++                      if (target == ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskID) {
++                              phys_disk_num = ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskNum;
++                              quiese_io_flag=1;
++                      }
++      }
++      /* if RAID Volume, then quiesce io to phys disk*/
++      if (quiese_io_flag==1) {
++              if (mptctl_raid_get_volume_id(ioc, phys_disk_num,
++                  &volume_id, &volume_bus) != 0) {
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto cim_stp_passthru_exit;
++              }
++              mptctl_do_raid(ioc,
++                  MPI_RAID_ACTION_QUIESCE_PHYS_IO,
++                  phys_disk_num, volume_bus, volume_id, NULL);
++      }
++#endif
++      /* Get a free request frame and save the message context.
++       */
++      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++              dctlprintk((": no msg frames!\n"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_stp_passthru_exit;
++        }
++
++      mpi_hdr = (MPIHeader_t *) mf;
++      pSataRequest = (pSataPassthroughRequest_t) mf;
++      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
++
++      memset(pSataRequest,0,sizeof(pSataPassthroughRequest_t));
++
++      pSataRequest->TargetID = target;
++      pSataRequest->Bus = bus;
++      pSataRequest->Function = MPI_FUNCTION_SATA_PASSTHROUGH;
++      pSataRequest->PassthroughFlags = cpu_to_le16(karg.Parameters.uFlags);
++      pSataRequest->ConnectionRate = karg.Parameters.bConnectionRate;
++      pSataRequest->MsgContext = mpi_hdr->MsgContext;
++      pSataRequest->DataLength = cpu_to_le32(request_data_sz);
++      pSataRequest->MsgFlags = 0;
++      memcpy( pSataRequest->CommandFIS,karg.Parameters.bCommandFIS, 20);
++
++      psge = (char *)&pSataRequest->SGL;
++      if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) {
++              flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
++      } else if (karg.Parameters.uFlags & CSMI_SAS_STP_READ) {
++              flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
++      }else {
++              flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++                              MPI_SGE_FLAGS_DIRECTION |
++                              mpt_addr_size() )
++                              << MPI_SGE_FLAGS_SHIFT;
++      }
++
++      flagsLength |= request_data_sz;
++      if (request_data_sz > 0) {
++              request_data = pci_alloc_consistent(
++                  ioc->pcidev, request_data_sz, &request_data_dma);
++
++              if (request_data == NULL) {
++                      dctlprintk((": pci_alloc_consistent: FAILED\n"));
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      mpt_free_msg_frame(ioc, mf);
++                      goto cim_stp_passthru_exit;
++              }
++
++              mpt_add_sge(psge, flagsLength, request_data_dma);
++              if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) {
++                      if (copy_from_user(request_data,
++                          karg.bDataBuffer,
++                          request_data_sz)) {
++                              printk(KERN_ERR
++                                  "%s::%s() @%d - Unable to read user data "
++                                  "struct @ %p\n",
++                                  __FILE__, __FUNCTION__, __LINE__,
++                                  (void*)karg.bDataBuffer);
++                              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                              mpt_free_msg_frame(ioc, mf);
++                              goto cim_stp_passthru_exit;
++                      }
++              }
++      } else {
++              mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
++      }
++
++      /* The request is complete. Set the timer parameters
++       * and issue the request.
++       */
++      ioc->ioctl->wait_done = 0;
++      mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++      /* Now wait for the command to complete */
++      wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++      ii = wait_event_timeout(mptctl_wait,
++           ioc->ioctl->wait_done == 1,
++           HZ*wait_timeout);
++
++      if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++      /* Now we need to reset the board */
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              mpt_free_msg_frame(ioc, mf);
++              mptctl_timeout_expired(ioc->ioctl);
++              goto cim_stp_passthru_exit;
++      }
++
++      memset(&karg.Status,0,sizeof(CSMI_SAS_STP_PASSTHRU_STATUS));
++
++      if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) {
++              dctlprintk((": STP Passthru: oh no, there is no reply!!"));
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_stp_passthru_exit;
++      }
++
++      /* process the completed Reply Message Frame */
++      pSataReply = (pSataPassthroughReply_t ) ioc->ioctl->ReplyFrame;
++
++      if ((le16_to_cpu(pSataReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) &&
++          (le16_to_cpu(pSataReply->IOCStatus) != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN )) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              dctlprintk((": STP Passthru: "));
++              dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
++                  le16_to_cpu(pSataReply->IOCStatus),
++                  le32_to_cpu(pSataReply->IOCLogInfo),
++                  pSataReply->SASStatus));
++      }
++
++      karg.Status.bConnectionStatus =
++          map_sas_status_to_csmi(pSataReply->SASStatus);
++
++      memcpy(karg.Status.bStatusFIS,pSataReply->StatusFIS, 20);
++
++      /*
++       * for now, just zero out uSCR array,
++       * then copy the one dword returned
++       * in the reply frame into uSCR[0]
++       */
++      memset( karg.Status.uSCR, 0, 64);
++      karg.Status.uSCR[0] = le32_to_cpu(pSataReply->StatusControlRegisters);
++
++      if((le32_to_cpu(pSataReply->TransferCount)) && (request_data) &&
++          (karg.Parameters.uFlags & CSMI_SAS_STP_READ)) {
++              karg.Status.uDataBytes =
++                  min(le32_to_cpu(pSataReply->TransferCount),request_data_sz);
++              if (copy_to_user((char *)uarg->bDataBuffer,
++                  request_data, karg.Status.uDataBytes)) {
++                      printk(KERN_ERR "%s::%s() @%d - "
++                          "Unable to write data to user %p\n",
++                          __FILE__, __FUNCTION__, __LINE__,
++                          (void*)karg.bDataBuffer);
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              }
++      }
++
++cim_stp_passthru_exit:
++
++      ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++          MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++          MPT_IOCTL_STATUS_RF_VALID );
++
++      if (request_data)
++              pci_free_consistent(ioc->pcidev, request_data_sz,
++                  (u8 *)request_data, request_data_dma);
++
++#ifdef QUIESE_IO
++      if (quiese_io_flag)
++              mptctl_do_raid(ioc,
++                  MPI_RAID_ACTION_ENABLE_PHYS_IO,
++                  phys_disk_num, volume_bus, volume_id, NULL);
++#endif
++
++      /* Copy th data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++          offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER,bDataBuffer))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                      "Unable to write out csmi_sas_ssp_passthru @ %p\n",
++                              __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Firmware Download command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_firmware_download(unsigned long arg)
++{
++      CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER        karg;
++      MPT_ADAPTER                     *ioc = NULL;
++      int                             iocnum;
++      pMpiFwHeader_t                  pFwHeader=NULL;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg,
++              sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_firmware_download struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* Default to success.*/
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++      karg.Information.usStatus = CSMI_SAS_FWD_SUCCESS;
++      karg.Information.usSeverity = CSMI_SAS_FWD_INFORMATION;
++
++      /* some checks of the incoming frame */
++      if ((karg.Information.uBufferLength +
++          sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD)) >
++          karg.IoctlHeader.Length) {
++              karg.IoctlHeader.ReturnCode =
++                  CSMI_SAS_STATUS_INVALID_PARAMETER;
++              karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
++              goto cim_firmware_download_exit;
++      }
++
++      if ( karg.Information.uDownloadFlags &
++          (CSMI_SAS_FWD_SOFT_RESET | CSMI_SAS_FWD_VALIDATE)) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
++              karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
++              goto cim_firmware_download_exit;
++      }
++
++      /* now we need to alloc memory so we can pull in the
++       * fw image attached to end of incomming packet.
++       */
++      pFwHeader = kmalloc(karg.Information.uBufferLength, GFP_KERNEL);
++      if(pFwHeader==NULL){
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
++              karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
++              goto cim_firmware_download_exit;
++      }
++
++      if (copy_from_user(pFwHeader, uarg->bDataBuffer,
++              karg.Information.uBufferLength)) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in pFwHeader @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if ( !((pFwHeader->Signature0 == MPI_FW_HEADER_SIGNATURE_0) &&
++          (pFwHeader->Signature1 == MPI_FW_HEADER_SIGNATURE_1) &&
++          (pFwHeader->Signature2 == MPI_FW_HEADER_SIGNATURE_2))) {
++              // the signature check failed
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
++              karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
++              goto cim_firmware_download_exit;
++      }
++
++      if ( mptctl_do_fw_download(karg.IoctlHeader.IOControllerNumber,
++          uarg->bDataBuffer, karg.Information.uBufferLength)
++          != 0) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
++              karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
++              goto cim_firmware_download_exit;
++      }
++
++      if((karg.Information.uDownloadFlags & CSMI_SAS_FWD_SOFT_RESET) ||
++          (karg.Information.uDownloadFlags & CSMI_SAS_FWD_HARD_RESET)) {
++              if (mpt_HardResetHandler(ioc, CAN_SLEEP) != 0) {
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
++                      karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
++              }
++      }
++
++cim_firmware_download_exit:
++
++      if(pFwHeader)
++              kfree(pFwHeader);
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++                              sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                      "Unable to write out csmi_sas_firmware_download @ %p\n",
++                              __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get RAID Info command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_raid_info(unsigned long arg)
++{
++      CSMI_SAS_RAID_INFO_BUFFER __user *uarg =  (void __user *) arg;
++      CSMI_SAS_RAID_INFO_BUFFER        karg;
++      MPT_ADAPTER             *ioc = NULL;
++      int                             iocnum;
++    u32             raidFlags;
++      u8                              maxRaidTypes;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_get_raid_info struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++      if( !mpt_findImVolumes(ioc)) {
++              if ( ioc->raid_data.pIocPg2 ) {
++                      karg.Information.uNumRaidSets = ioc->raid_data.pIocPg2->NumActiveVolumes;
++            // uMaxDrivesPerSet hard coded until value is available through RAID config page
++                      karg.Information.uMaxDrivesPerSet = 8;
++            karg.Information.uMaxRaidSets = ioc->raid_data.pIocPg2->MaxVolumes;
++            // For bMaxRaidSets, count bits set in bits 0-6 of CapabilitiesFlags
++            raidFlags = ioc->raid_data.pIocPg2->CapabilitiesFlags & 0x0000007F;
++            for( maxRaidTypes=0; raidFlags; maxRaidTypes++ )
++            {
++                raidFlags &= raidFlags - 1;
++            }
++            karg.Information.bMaxRaidTypes = maxRaidTypes;
++            // ulMinRaidSetBlocks hard coded to 1MB until available from config page
++            karg.Information.ulMinRaidSetBlocks = 2048;
++            karg.Information.ulMaxRaidSetBlocks = 
++                (ioc->raid_data.pIocPg2->CapabilitiesFlags & 
++                 MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING)
++                ? 0xffffffffffffffffULL : 0x00000000ffffffffULL;
++            karg.Information.uMaxPhysicalDrives = ioc->raid_data.pIocPg2->MaxPhysDisks;
++            karg.Information.uMaxExtents = 1;
++            karg.Information.uMaxModules = 0;
++            karg.Information.uMaxTransformationMemory = 0;
++            karg.Information.uChangeCount = ioc->csmi_change_count;
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++              }
++      }
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++                              sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                      "Unable to write out csmi_sas_get_raid_info @ %p\n",
++                              __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*    mptscsih_do_raid - Format and Issue a RAID volume request message.
++ *    @ioc: Pointer to MPT_ADAPTER structure
++ *    @action: What do be done.
++ *    @PhysDiskNum: Logical target id.
++ *    @VolumeBus: Target locations bus.
++ *    @VolumeId: Volume id
++ *
++ *    Returns: < 0 on a fatal error
++ *            0 on success
++ *
++ *    Remark: Wait to return until reply processed by the ISR.
++ */
++static int
++mptctl_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, u8 VolumeId, pMpiRaidActionReply_t reply)
++{
++      MpiRaidActionRequest_t  *pReq;
++      MpiRaidActionReply_t    *pReply;
++      MPT_FRAME_HDR           *mf;
++      int ii;
++
++      /* Get and Populate a free Frame
++       */
++      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++              dctlprintk((": no msg frames!\n"));
++              return -EAGAIN;
++      }
++      pReq = (MpiRaidActionRequest_t *)mf;
++      pReq->Action = action;
++      pReq->Reserved1 = 0;
++      pReq->ChainOffset = 0;
++      pReq->Function = MPI_FUNCTION_RAID_ACTION;
++      pReq->VolumeID = VolumeId;
++      pReq->VolumeBus = VolumeBus;
++      pReq->PhysDiskNum = PhysDiskNum;
++      pReq->MsgFlags = 0;
++      pReq->Reserved2 = 0;
++      pReq->ActionDataWord = 0; /* Reserved for this action */
++      //pReq->ActionDataSGE = 0;
++
++      mpt_add_sge((char *)&pReq->ActionDataSGE,
++              MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
++
++      ioc->ioctl->wait_done = 0;
++      mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++      /* Now wait for the command to complete */
++      ii = wait_event_timeout(mptctl_wait,
++           ioc->ioctl->wait_done == 1,
++           HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
++
++      if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++      /* Now we need to reset the board */
++              mpt_free_msg_frame(ioc, mf);
++              mptctl_timeout_expired(ioc->ioctl);
++              return -ENODATA;
++      }
++
++      if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) &&
++          (reply != NULL)){
++              pReply = (MpiRaidActionReply_t *)&(ioc->ioctl->ReplyFrame);
++              memcpy(reply, pReply,
++                      min(ioc->reply_sz,
++                      4*pReply->MsgLength));
++      }
++
++      return 0;
++}
++
++#ifdef QUIESE_IO
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*    mptctl_raid_get_volume_id - figures out which Volume a PhysDisk belongs to.
++ *    @ioc: Pointer to MPT_ADAPTER structure
++ *    @PhysDiskNum: an unique number assigned by IOC to identify a specific IR phy disk
++ *
++ *    Returns: < 0 on a fatal error
++ *            0 on success
++ *
++ *    Following parameters are valid when successful return
++ *    @VolumeID - target device identification number of the volume
++ *    @VolumeBus - the SCSI bus number of the volume
++ *
++ */
++static int
++mptctl_raid_get_volume_id(MPT_ADAPTER *ioc, u8 PhysDiskNum, u8 *VolumeID, u8 *VolumeBus)
++{
++      CONFIGPARMS             cfg;
++      ConfigPageHeader_t      header;
++      dma_addr_t              volume0_dma;
++      int                     i,j;
++      int                     rc=0;
++      int                     volumepage0sz = 0;
++      pRaidVolumePage0_t      pVolume0 = NULL;
++
++      /*
++       * get RAID Volume Page 0
++       */
++      header.PageVersion = 0;
++      header.PageLength = 0;
++      header.PageNumber = 0;
++      header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
++      cfg.cfghdr.hdr = &header;
++      cfg.physAddr = -1;
++      cfg.pageAddr = 0;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++      if (mpt_config(ioc, &cfg) != 0) {
++              rc = -1;
++              goto mptctl_raid_get_volume_id_exit;
++      }
++
++      if (header.PageLength == 0) {
++              rc = -1;
++              goto mptctl_raid_get_volume_id_exit;
++      }
++
++      volumepage0sz = header.PageLength * 4;
++      pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
++          &volume0_dma);
++      if (!pVolume0) {
++              rc = -1;
++              goto mptctl_raid_get_volume_id_exit;
++      }
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++      cfg.physAddr = volume0_dma;
++
++      for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){
++              *VolumeID = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID;
++              *VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
++              cfg.pageAddr = (*VolumeBus << 8) + *VolumeID;
++              if (mpt_config(ioc, &cfg) != 0){
++                      rc = -1;
++                      goto mptctl_raid_get_volume_id_exit;
++              }
++              for (j=0; j<pVolume0->NumPhysDisks; j++){
++                      if (PhysDiskNum == pVolume0->PhysDisk[i].PhysDiskNum)
++                              goto mptctl_raid_get_volume_id_exit;
++              }
++      }
++
++mptctl_raid_get_volume_id_exit:
++
++      if (pVolume0 != NULL)
++              pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
++                  volume0_dma);
++
++      return rc;
++}
++#endif
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* mptctl_raid_inq
++ * @ioc = per host instance
++ * @opcode = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH or MPI_FUNCTION_SCSI_IO_REQUEST
++ * @target = target id
++ * @inq_vpd = inquiry data, returned
++ * @inq_vpd_sz = maximum size of inquiry data
++ *
++ * Return = 0(sucess), non-zero(failure)
++ */
++static int
++mptctl_raid_inq(MPT_ADAPTER *ioc, u8 opcode, u8 target, u8 inq_vpd_page, u8 * inq_vpd, u32 inq_vpd_sz)
++{
++      MPT_FRAME_HDR           *mf = NULL;
++      MPIHeader_t             *mpi_hdr;
++      pSCSIIORequest_t        pScsiRequest;
++      u16                             req_idx;
++      char                        *psge;
++      u8                              inq_vpd_cdb[6];
++      u8                              *request_data=NULL;
++      dma_addr_t                  request_data_dma;
++      u32                             request_data_sz;
++      int                         rc=0,ii;
++
++      request_data_sz = 0xFFFF; /* max data size */
++
++    /* fill-in cdb */
++    inq_vpd_cdb[0] = 0x12;
++    if (inq_vpd_page) {
++        inq_vpd_cdb[1] = 0x01; /* evpd bit */
++        inq_vpd_cdb[2] = inq_vpd_page;
++    }
++    inq_vpd_cdb[3] = (u8)(request_data_sz >> 8);
++    inq_vpd_cdb[4] = (u8)request_data_sz;
++
++      /* Get a free request frame and save the message context.
++       */
++      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++              dctlprintk((": no msg frames!\n"));
++              goto mptctl_raid_inq_exit;
++    }
++
++      mpi_hdr = (MPIHeader_t *) mf;
++      pScsiRequest = (pSCSIIORequest_t) mf;
++      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
++
++      memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
++      pScsiRequest->Function = opcode;
++      pScsiRequest->TargetID = target;
++      pScsiRequest->Bus = 0;
++      pScsiRequest->CDBLength = 6;
++      pScsiRequest->DataLength = cpu_to_le16(request_data_sz);
++      pScsiRequest->MsgContext = mpi_hdr->MsgContext;
++      memcpy(pScsiRequest->CDB,inq_vpd_cdb,pScsiRequest->CDBLength);
++      pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
++      pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
++
++      /* setup sense
++       */
++      pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
++      pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
++          (req_idx * MPT_SENSE_BUFFER_ALLOC));
++
++      request_data = pci_alloc_consistent(
++          ioc->pcidev, request_data_sz, &request_data_dma);
++
++      if (request_data == NULL) {
++              mpt_free_msg_frame(ioc, mf);
++              rc=-1;
++              goto mptctl_raid_inq_exit;
++      }
++
++      memset(request_data,0,request_data_sz);
++      psge = (char *)&pScsiRequest->SGL;
++      mpt_add_sge(psge, (MPT_SGE_FLAGS_SSIMPLE_READ | 0xFC) , request_data_dma);
++
++      /* The request is complete. Set the timer parameters
++       * and issue the request.
++       */
++      ioc->ioctl->wait_done = 0;
++      mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++      /* Now wait for the command to complete */
++      ii = wait_event_timeout(mptctl_wait,
++           ioc->ioctl->wait_done == 1,
++           HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
++
++      if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++      /* Now we need to reset the board */
++              rc=-1;
++              mpt_free_msg_frame(ioc, mf);
++              mptctl_timeout_expired(ioc->ioctl);
++              goto mptctl_raid_inq_exit;
++      }
++
++    /* copy the request_data */
++    memcpy(inq_vpd,request_data,min(request_data_sz,inq_vpd_sz));
++
++mptctl_raid_inq_exit:
++
++      if (request_data)
++              pci_free_consistent(ioc->pcidev, request_data_sz,
++                  request_data, request_data_dma);
++
++    return rc;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get RAID Config command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_raid_config(unsigned long arg)
++{
++      CSMI_SAS_RAID_CONFIG_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_RAID_CONFIG_BUFFER      karg,*pKarg=NULL;
++      CONFIGPARMS                     cfg;
++      ConfigPageHeader_t              header;
++      MPT_ADAPTER                     *ioc = NULL;
++      int                             iocnum;
++      u8                              volumeID, VolumeBus, physDiskNum, physDiskNumMax, found;
++      int                             volumepage0sz = 0, physdiskpage0sz = 0, ioc_page5_sz = 0;
++      dma_addr_t                      volume0_dma, physdisk0_dma, ioc_page5_dma;
++      pRaidVolumePage0_t              pVolume0 = NULL;
++      pRaidPhysDiskPage0_t            pPhysDisk0 = NULL;
++      pMpiRaidActionReply_t           pRaidActionReply = NULL;
++      pIOCPage5_t                     pIocPage5 = NULL;
++      int                             i, idx, csmi_sas_raid_config_buffer_sz;
++    int                 copy_buffer_sz=0;
++      sas_device_info_t               *sasDevice;
++      u32                             device_info=0;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_get_raid_config struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      csmi_sas_raid_config_buffer_sz = karg.IoctlHeader.Length;
++      pKarg = kmalloc(csmi_sas_raid_config_buffer_sz, GFP_KERNEL);
++      if(!pKarg){
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to malloc @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__,pKarg);
++              return -EFAULT;
++      }
++
++      if (copy_from_user(pKarg, uarg, csmi_sas_raid_config_buffer_sz)) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_get_raid_config struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              kfree(pKarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(pKarg);
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(pKarg);
++              return -ENODEV;
++      }
++
++      if (!ioc->raid_data.isRaid) {
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_raid_config_exit;
++      }
++
++    if (pKarg->Configuration.uChangeCount != 0 &&
++        pKarg->Configuration.uChangeCount != ioc->csmi_change_count ) {
++        pKarg->IoctlHeader.ReturnCode = 
++              CSMI_SAS_STATUS_INVALID_PARAMETER;
++        //pKarg->Configuration.uFailureCode = 
++          //  CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
++        goto cim_get_raid_config_exit;
++    }
++
++      /* check to see if the input uRaidSetIndex is greater than the number of RAID sets */
++      if(pKarg->Configuration.uRaidSetIndex >=
++          ioc->raid_data.pIocPg2->NumActiveVolumes) {
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_RAID_SET_OUT_OF_RANGE;
++              goto cim_get_raid_config_exit;
++      }
++
++      /*
++       * get RAID Volume Page 0
++       */
++      volumeID = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeID;
++      VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeBus;
++
++      header.PageVersion = 0;
++      header.PageLength = 0;
++      header.PageNumber = 0;
++      header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
++      cfg.cfghdr.hdr = &header;
++      cfg.physAddr = -1;
++      cfg.pageAddr = (VolumeBus << 8) + volumeID;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++      if (mpt_config(ioc, &cfg) != 0) {
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_raid_config_exit;
++      }
++
++      if (header.PageLength == 0) {
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_raid_config_exit;
++      }
++
++      volumepage0sz = header.PageLength * 4;
++      pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
++          &volume0_dma);
++      if (!pVolume0) {
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_raid_config_exit;
++      }
++
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++      cfg.physAddr = volume0_dma;
++      if (mpt_config(ioc, &cfg) != 0){
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_raid_config_exit;
++      }
++
++      pKarg->Configuration.uCapacity =
++              (le32_to_cpu(pVolume0->MaxLBA)+1)/2048;
++      pKarg->Configuration.uStripeSize =
++              le32_to_cpu(pVolume0->StripeSize)/2;
++
++      switch(pVolume0->VolumeType) {
++      case MPI_RAID_VOL_TYPE_IS:
++              pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_0;
++              break;
++      case MPI_RAID_VOL_TYPE_IME:
++              pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_10;
++              break;
++      case MPI_RAID_VOL_TYPE_IM:
++              pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_1;
++              break;
++      default:
++              pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_OTHER;
++              break;
++      }
++
++    switch (pVolume0->VolumeStatus.State) {
++      case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
++              pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OK;
++              break;
++    case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
++        /* Volume is degraded, check if Resyncing or Inactive */
++        if (pVolume0->VolumeStatus.State & 
++            MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
++            pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_REBUILDING;
++        }
++        else if (pVolume0->VolumeStatus.State & 
++                 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE) {
++            pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OFFLINE;
++        }
++        else {
++            pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_DEGRADED;
++        }
++              break;
++      case MPI_RAIDVOL0_STATUS_STATE_FAILED:
++              pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_FAILED;
++              break;
++      }
++
++    pKarg->Configuration.bInformation = 0;  /* default */
++      if(pVolume0->VolumeStatus.Flags &
++          MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ) {
++
++              uint64_t        * ptrUint64;
++              uint64_t        totalBlocks64, blocksRemaining64;
++              uint32_t        totalBlocks32, blocksRemaining32;
++
++              /* get percentage complete */
++              pRaidActionReply = kmalloc( sizeof(MPI_RAID_VOL_INDICATOR) +
++                  offsetof(MSG_RAID_ACTION_REPLY,ActionData),
++                  GFP_KERNEL);
++
++              if(pRaidActionReply == NULL){
++                      printk(KERN_ERR "%s@%d::%s() - "
++                          "Unable to malloc @ %p\n",
++                          __FILE__, __LINE__, __FUNCTION__,pKarg);
++                      goto cim_get_raid_config_exit;
++              }
++
++              mptctl_do_raid(ioc,
++                  MPI_RAID_ACTION_INDICATOR_STRUCT,
++                  0, VolumeBus, volumeID, pRaidActionReply);
++
++              ptrUint64       = (uint64_t *)&pRaidActionReply->ActionData;
++              totalBlocks64     = *ptrUint64;
++              ptrUint64++;
++              blocksRemaining64 = *ptrUint64;
++              while(totalBlocks64 > 0xFFFFFFFFUL){
++                      totalBlocks64 = totalBlocks64 >> 1;
++                      blocksRemaining64 = blocksRemaining64 >> 1;
++              }
++              totalBlocks32 = (uint32_t)totalBlocks64;
++              blocksRemaining32 = (uint32_t)blocksRemaining64;
++
++              if(totalBlocks32)
++                      pKarg->Configuration.bInformation =
++                          (totalBlocks32 - blocksRemaining32) /
++                          (totalBlocks32 / 100);
++
++              kfree(pRaidActionReply);
++      }
++
++    /* fill-in more information depending on data type */
++    if (pKarg->Configuration.bDataType == CSMI_SAS_RAID_DATA_ADDITIONAL_DATA) {
++        pKarg->Configuration.Data->bLabel[0] = '\0';
++        pKarg->Configuration.Data->bRaidSetLun[1] = 0;
++        pKarg->Configuration.Data->bWriteProtection = 
++            CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN;
++        pKarg->Configuration.Data->bCacheSetting = 
++            CSMI_SAS_RAID_SET_CACHE_UNKNOWN;
++        pKarg->Configuration.Data->bCacheRatio = 0;
++        pKarg->Configuration.Data->usBlockSize = 512;
++        pKarg->Configuration.Data->ulRaidSetExtentOffset = 0;
++        pKarg->Configuration.Data->ulRaidSetBlocks = le32_to_cpu(pVolume0->MaxLBA);
++        if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS ||
++            pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME ) {
++            pKarg->Configuration.Data->uStripeSizeInBlocks = 
++                le32_to_cpu(pVolume0->StripeSize);
++        }
++        else {
++            pKarg->Configuration.Data->uStripeSizeInBlocks = 0;
++        }
++        pKarg->Configuration.Data->uSectorsPerTrack = 128;
++        for (i=0; i<16; i++) {
++            // unsupported
++            pKarg->Configuration.Data->bApplicationScratchPad[i] = 0xFF;
++        }
++    }
++    else if( pKarg->Configuration.bDataType == CSMI_SAS_RAID_DATA_DEVICE_ID ) {
++        /* Send inquiry to get VPD Page 0x83 */
++        u8 * vpd_page=NULL;
++        u32 vpd_page_sz;
++        vpd_page_sz = pKarg->IoctlHeader.Length - sizeof(CSMI_SAS_RAID_CONFIG);
++              vpd_page = kmalloc(vpd_page_sz, GFP_KERNEL);
++        if (mptctl_raid_inq(ioc, MPI_FUNCTION_SCSI_IO_REQUEST, volumeID, 0x83, vpd_page, vpd_page_sz) != 0) {
++            pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      kfree(vpd_page);
++            goto cim_get_raid_config_exit;
++        }
++        memset(&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage,
++               0,vpd_page_sz);
++        memcpy(&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage, 
++               vpd_page,vpd_page_sz);
++              kfree(vpd_page);
++    }
++
++    if (pKarg->Configuration.bDataType != CSMI_SAS_RAID_DATA_DRIVES) {
++        pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++        goto cim_get_raid_config_exit;
++    }
++
++    /* suppress drive information */
++    if (pKarg->Configuration.bDriveCount == 
++        CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) {
++            pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++            goto cim_get_raid_config_exit;
++    }
++
++      /* get hotspare info, used later in this function */
++      if (pVolume0->VolumeSettings.HotSparePool) {
++              /* Read and save IOC Page 5
++               */
++              header.PageVersion = 0;
++              header.PageLength = 0;
++              header.PageNumber = 5;
++              header.PageType = MPI_CONFIG_PAGETYPE_IOC;
++              cfg.cfghdr.hdr = &header;
++              cfg.physAddr = -1;
++              cfg.pageAddr = 0;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++              cfg.dir = 0;
++              cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++              if ((mpt_config(ioc, &cfg)==0) && (header.PageLength)) {
++                      ioc_page5_sz = header.PageLength * 4;
++                      pIocPage5 = pci_alloc_consistent(ioc->pcidev,
++                          ioc_page5_sz,
++                          &ioc_page5_dma);
++                      memset(pIocPage5,0,ioc_page5_sz);
++                      if (ioc_page5_dma) {
++                              cfg.physAddr = ioc_page5_dma;
++                              cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++                              mpt_config(ioc, &cfg);
++                      }
++              }
++      }
++
++      /*
++       * get RAID Physical Disk Page 0
++       */
++      header.PageVersion = 0;
++      header.PageLength = 0;
++      header.PageNumber = 0;
++      header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
++      cfg.cfghdr.hdr = &header;
++      cfg.physAddr = -1;
++      cfg.pageAddr = 0;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++      if (mpt_config(ioc, &cfg) != 0) {
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_raid_config_exit;
++      }
++
++      if (header.PageLength == 0) {
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_raid_config_exit;
++      }
++
++      physdiskpage0sz = header.PageLength * 4;
++      pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
++          &physdisk0_dma);
++      if (!pPhysDisk0) {
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_raid_config_exit;
++      }
++      cfg.physAddr = physdisk0_dma;
++
++      physDiskNumMax = (csmi_sas_raid_config_buffer_sz -
++          offsetof(CSMI_SAS_RAID_CONFIG,Drives))
++          / sizeof(CSMI_SAS_RAID_DRIVES);
++
++      pKarg->Configuration.bDriveCount=0;
++
++      for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
++
++              physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++              cfg.pageAddr = physDiskNum;
++              if (mpt_config(ioc, &cfg) != 0){
++                      pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto cim_get_raid_config_exit;
++              }
++              memset(&pKarg->Configuration.Drives[i],0,
++                  sizeof(CSMI_SAS_RAID_DRIVES));
++              memcpy(pKarg->Configuration.Drives[i].bModel,
++                  pPhysDisk0->InquiryData.VendorID,
++                  offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
++              memcpy(pKarg->Configuration.Drives[i].bFirmware,
++                      pPhysDisk0->InquiryData.ProductRevLevel,
++                      sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
++              if ((pPhysDisk0->ExtDiskIdentifier[0] == 'A') &&
++                  (pPhysDisk0->ExtDiskIdentifier[1] == 'T') &&
++                  (pPhysDisk0->ExtDiskIdentifier[2] == 'A')) {
++                      memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
++                              &pPhysDisk0->ExtDiskIdentifier[4],
++                              4);
++                      memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
++                              &pPhysDisk0->DiskIdentifier,
++                              sizeof(pPhysDisk0->DiskIdentifier));
++              } else {
++                      memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
++                              pPhysDisk0->DiskIdentifier,
++                              sizeof(pPhysDisk0->DiskIdentifier));
++              }
++
++              pKarg->Configuration.Drives[i].bDriveUsage =
++                  (pPhysDisk0->PhysDiskStatus.Flags &
++                  MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) ?
++                  CSMI_SAS_DRIVE_CONFIG_NOT_USED :
++                  CSMI_SAS_DRIVE_CONFIG_MEMBER;
++
++              pKarg->Configuration.Drives[i].bDriveStatus =
++                  CSMI_SAS_DRIVE_STATUS_OK;
++        if (pPhysDisk0->PhysDiskStatus.State == 
++            MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED) {
++            pKarg->Configuration.Drives[i].bDriveStatus = 
++                CSMI_SAS_DRIVE_STATUS_OFFLINE;
++        }
++        else if(pPhysDisk0->PhysDiskStatus.State) {
++                      pKarg->Configuration.Drives[i].bDriveStatus =
++                          CSMI_SAS_DRIVE_STATUS_FAILED;
++                      if(pKarg->Configuration.bStatus ==
++                          CSMI_SAS_RAID_SET_STATUS_DEGRADED)
++                              pKarg->Configuration.bInformation = i;
++              }
++              else if((pVolume0->VolumeStatus.Flags &
++                  MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) &&
++                  (pPhysDisk0->PhysDiskStatus.Flags &
++                  MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
++                      pKarg->Configuration.Drives[i].bDriveStatus =
++                          CSMI_SAS_DRIVE_STATUS_REBUILDING;
++              else if(pPhysDisk0->ErrorData.SmartCount)
++                      pKarg->Configuration.Drives[i].bDriveStatus =
++                      CSMI_SAS_DRIVE_STATUS_DEGRADED;
++
++              /* Search the list for the matching SAS address. */
++              found = FALSE;
++              list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++                      /* Found the matching device. */
++                      if ((pPhysDisk0->PhysDiskIOC == sasDevice->Bus) &&
++                              (pPhysDisk0->PhysDiskID ==
++                               sasDevice->TargetId)) {
++                              u64 SASAddress64;
++                              found = TRUE;
++
++                              SASAddress64 =
++                                  reverse_byte_order64(&sasDevice->SASAddress);
++                              memcpy(pKarg->Configuration.Drives[i].bSASAddress,
++                                 &SASAddress64,sizeof(u64));
++                              memset(pKarg->Configuration.Drives[i].bSASLun,
++                                  0, sizeof(pKarg->Configuration.Drives[i].bSASLun));
++                              device_info = sasDevice->DeviceInfo;
++                if (device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) {
++                    pKarg->Configuration.Drives[i].bDriveType = 
++                        CSMI_SAS_DRIVE_TYPE_SATA;
++                }
++                else { /* drive in a volume can only be SAS/SATA */
++                    pKarg->Configuration.Drives[i].bDriveType = 
++                        CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
++                }
++                              break;
++                      } else
++                              continue; /* Keep looking. */
++              }
++        pKarg->Configuration.Drives[i].usBlockSize = 512;
++              pKarg->Configuration.Drives[i].uDriveIndex = pPhysDisk0->PhysDiskNum;
++        if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IM) {
++            pKarg->Configuration.Drives[i].ulTotalUserBlocks = 
++                le32_to_cpu(pVolume0->MaxLBA) + 1;
++        }
++        else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS) {
++            pKarg->Configuration.Drives[i].ulTotalUserBlocks = 
++                (le32_to_cpu(pVolume0->MaxLBA) + 1) / (pVolume0->NumPhysDisks);
++        }
++        else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME) {
++            pKarg->Configuration.Drives[i].ulTotalUserBlocks = 
++                ((le32_to_cpu(pVolume0->MaxLBA) + 1) / (pVolume0->NumPhysDisks)) * 2;
++        }
++        pKarg->Configuration.bDriveCount++;
++      }
++
++      /* adding hot spare info at the end */
++      if ((pVolume0->VolumeSettings.HotSparePool) && (pIocPage5 != NULL)) {
++              for (idx = 0, i = pVolume0->NumPhysDisks ;
++                  idx < pIocPage5->NumHotSpares ; idx++) {
++                      if (i >= physDiskNumMax)
++                              break;
++                      if ((pVolume0->VolumeSettings.HotSparePool &
++                          pIocPage5->HotSpare[idx].HotSparePool) == 0)
++                              continue;
++                      if(pIocPage5->HotSpare[idx].Flags !=
++                          MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE)
++                          continue;
++                      physDiskNum = pIocPage5->HotSpare[idx].PhysDiskNum;
++                      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++                      cfg.pageAddr = physDiskNum;
++                      if (mpt_config(ioc, &cfg) != 0)
++                              continue;
++                      /* Search the list for the matching SAS address. */
++                      found = FALSE;
++                      list_for_each_entry(sasDevice, &ioc->sasDeviceList,
++                          list) {
++                              /* Found the matching device. */
++                              if ((pPhysDisk0->PhysDiskIOC ==
++                                      sasDevice->Bus) &&
++                                      (pPhysDisk0->PhysDiskID ==
++                                       sasDevice->TargetId)) {
++                                      u64 SASAddress64;
++
++                                      /* sanity checks */
++
++                                      /* don't mix SSP hot spare
++                                       * in SATA volume
++                                       */
++                                      if ((sasDevice->DeviceInfo &
++                                          MPI_SAS_DEVICE_INFO_SSP_TARGET) &&
++                                          (device_info &
++                                          MPI_SAS_DEVICE_INFO_SATA_DEVICE))
++                                              break;
++
++                                      /* don't mix SATA hot spare
++                                       * in SSP volume
++                                       */
++                                      if ((sasDevice->DeviceInfo &
++                                          MPI_SAS_DEVICE_INFO_SATA_DEVICE) &&
++                                          (device_info &
++                                          MPI_SAS_DEVICE_INFO_SSP_TARGET))
++                                              break;
++
++                                      /* capacity check for IM volumes*/
++                                      if ((pVolume0->VolumeType ==
++                                              MPI_RAID_VOL_TYPE_IM) &&
++                                          (le32_to_cpu(pVolume0->MaxLBA) +
++                                           (64*2*1024) /* metadata = 64MB*/ >
++                                          le32_to_cpu(pPhysDisk0->MaxLBA)))
++                                              break;
++
++                                      /* capacity check for IME volumes*/
++                                      if ((pVolume0->VolumeType ==
++                                              MPI_RAID_VOL_TYPE_IME) &&
++                                          (((le32_to_cpu(pVolume0->MaxLBA)/
++                                            pVolume0->NumPhysDisks) * 2) +
++                                           (64*2*1024 ) /*metadata = 64MB*/ >
++                                          le32_to_cpu(pPhysDisk0->MaxLBA)))
++                                              break;
++
++                                      found = TRUE;
++
++                                      SASAddress64 =
++                                          reverse_byte_order64(&sasDevice->SASAddress);
++                                      memcpy(pKarg->Configuration.Drives[i].bSASAddress,
++                                         &SASAddress64,sizeof(u64));
++                                      memset(pKarg->Configuration.Drives[i].bSASLun, 0,
++                                           sizeof(pKarg->Configuration.Drives[i].bSASLun));
++                                      break;
++                              } else
++                                      continue; /* Keep looking. */
++                      }
++                      if (found==FALSE)
++                              continue;
++                      memset(&pKarg->Configuration.Drives[i],0,
++                          sizeof(CSMI_SAS_RAID_DRIVES));
++                      memcpy(pKarg->Configuration.Drives[i].bModel,
++                          pPhysDisk0->InquiryData.VendorID,
++                          offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
++                      memcpy(pKarg->Configuration.Drives[i].bFirmware,
++                              pPhysDisk0->InquiryData.ProductRevLevel,
++                              sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
++                      if ((pPhysDisk0->ExtDiskIdentifier[0] == 'A') &&
++                          (pPhysDisk0->ExtDiskIdentifier[1] == 'T') &&
++                          (pPhysDisk0->ExtDiskIdentifier[2] == 'A')) {
++                              memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
++                                      &pPhysDisk0->ExtDiskIdentifier[4],
++                                      4);
++                              memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
++                                      &pPhysDisk0->DiskIdentifier,
++                                      sizeof(pPhysDisk0->DiskIdentifier));
++                      } else {
++                              memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
++                                      pPhysDisk0->DiskIdentifier,
++                                      sizeof(pPhysDisk0->DiskIdentifier));
++                      }
++                      pKarg->Configuration.Drives[i].bDriveStatus =
++                          CSMI_SAS_DRIVE_STATUS_OK;
++                      if(pPhysDisk0->PhysDiskStatus.State)
++                              pKarg->Configuration.Drives[i].bDriveStatus =
++                                  CSMI_SAS_DRIVE_STATUS_FAILED;
++                      else if(pPhysDisk0->ErrorData.SmartCount)
++                              pKarg->Configuration.Drives[i].bDriveStatus =
++                                  CSMI_SAS_DRIVE_STATUS_DEGRADED;
++                      pKarg->Configuration.Drives[i].bDriveUsage =
++                          CSMI_SAS_DRIVE_CONFIG_SPARE;
++                      i++;
++                      pKarg->Configuration.bDriveCount++;
++              }
++      }
++
++    // Only return data on the first 240 drives
++    if( pKarg->Configuration.bDriveCount > 0xF0 ) {
++        pKarg->Configuration.bDriveCount = 
++            CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG;
++    }
++
++      pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++cim_get_raid_config_exit:
++
++      if (pVolume0 != NULL)
++              pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
++                  volume0_dma);
++
++      if(pPhysDisk0 != NULL)
++              pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
++                  physdisk0_dma);
++
++      if(pIocPage5 != NULL)
++              pci_free_consistent(ioc->pcidev, ioc_page5_sz, pIocPage5,
++                  ioc_page5_dma);
++
++      /* Copy the data from kernel memory to user memory
++       */
++
++    /* find the buffer size to copy depending on how much is filled-in */
++    switch (pKarg->Configuration.bDataType) {
++    case CSMI_SAS_RAID_DATA_ADDITIONAL_DATA:
++        copy_buffer_sz = sizeof(IOCTL_HEADER) +
++            offsetof(CSMI_SAS_RAID_CONFIG,Data) +
++            sizeof(CSMI_SAS_RAID_SET_ADDITIONAL_DATA);
++        break;
++    case CSMI_SAS_RAID_DATA_DRIVES:
++        if (pKarg->Configuration.bDriveCount == 
++            CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) {
++            copy_buffer_sz = sizeof(IOCTL_HEADER) +
++                offsetof(CSMI_SAS_RAID_CONFIG,Drives);
++        }
++        else {
++            copy_buffer_sz = sizeof(IOCTL_HEADER) +
++                offsetof(CSMI_SAS_RAID_CONFIG,Drives) +
++                (pKarg->Configuration.bDriveCount * sizeof(CSMI_SAS_RAID_DRIVES));
++        }
++        break;
++    case CSMI_SAS_RAID_DATA_DEVICE_ID:
++        copy_buffer_sz = sizeof(IOCTL_HEADER) +
++            offsetof(CSMI_SAS_RAID_CONFIG,DeviceId) +
++            sizeof(CSMI_SAS_RAID_DEVICE_ID);
++        break;
++    }
++
++    if (copy_to_user((char *)arg, pKarg, copy_buffer_sz)) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                     "Unable to write out csmi_sas_get_raid_config @ %p\n",
++                         __FILE__, __LINE__, __FUNCTION__, uarg);
++              kfree(pKarg);
++              return -EFAULT;
++    }
++
++    kfree(pKarg);
++
++      return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get RAID Features command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_raid_features(unsigned long arg)
++{
++      CSMI_SAS_RAID_FEATURES_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_RAID_FEATURES_BUFFER karg, *pKarg=NULL;
++      int i, csmi_sas_raid_features_buffer_sz, iocnum;
++    MPT_ADAPTER                       *ioc = NULL;
++
++    u8 raidTypes[4] = { CSMI_SAS_RAID_TYPE_0, CSMI_SAS_RAID_TYPE_10,
++                        CSMI_SAS_RAID_TYPE_1, CSMI_SAS_RAID_TYPE_1E };
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      csmi_sas_raid_features_buffer_sz = karg.IoctlHeader.Length;
++      pKarg = kmalloc(csmi_sas_raid_features_buffer_sz, GFP_KERNEL);
++      if(!pKarg){
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to malloc @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__,pKarg);
++              return -EFAULT;
++      }
++
++      if (copy_from_user(pKarg, uarg, csmi_sas_raid_features_buffer_sz)) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              kfree(pKarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(pKarg);
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(pKarg);
++              return -ENODEV;
++      }
++
++    if (pKarg->Information.uChangeCount != 0 &&
++        pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
++        pKarg->IoctlHeader.ReturnCode = 
++                      CSMI_SAS_STATUS_INVALID_PARAMETER;
++        //pKarg->Information.uFailureCode = 
++              //      CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
++        goto cim_get_raid_features_exit;
++    }
++
++    pKarg->Information.uFeatures = CSMI_SAS_RAID_FEATURE_REBUILD;
++    pKarg->Information.bDefaultTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.bTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.bDefaultRebuildPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.bRebuildPriority = pKarg->Information.bDefaultRebuildPriority;
++    pKarg->Information.bDefaultSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.bSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN;
++    pKarg->Information.uRaidSetTransformationRules = 0;
++    for (i=0; i<4; i++) {
++        pKarg->Information.RaidType[i].bRaidType = raidTypes[i];
++        // Only support 64K stripe size
++        pKarg->Information.RaidType[i].uSupportedStripeSizeMap = 0x80;
++    }
++    pKarg->Information.RaidType[i].bRaidType = CSMI_SAS_RAID_TYPE_END;
++    pKarg->Information.bCacheRatiosSupported[0] = CSMI_SAS_RAID_CACHE_RATIO_END;
++
++cim_get_raid_features_exit:
++
++    /*
++     * Copy the data from kernel memory to user memory
++     */
++    if (copy_to_user((char *)arg, pKarg,
++        sizeof(CSMI_SAS_RAID_FEATURES_BUFFER))) {
++        printk(KERN_ERR "%s@%d::%s() - "
++               "Unable to write out csmi_sas_get_raid_features @ %p\n",
++               __FILE__, __LINE__, __FUNCTION__, uarg);
++        kfree(pKarg);
++        return -EFAULT;
++    }
++
++    kfree(pKarg);
++
++    return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get RAID Control command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_raid_control(unsigned long arg)
++{
++      CSMI_SAS_RAID_CONTROL_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_RAID_CONTROL_BUFFER karg, *pKarg=NULL;
++      int csmi_sas_raid_control_buffer_sz, iocnum;
++    MPT_ADAPTER                       *ioc = NULL;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_get_raid_control struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      csmi_sas_raid_control_buffer_sz = karg.IoctlHeader.Length;
++      pKarg = kmalloc(csmi_sas_raid_control_buffer_sz, GFP_KERNEL);
++      if(!pKarg){
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to malloc @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__,pKarg);
++              return -EFAULT;
++      }
++
++      if (copy_from_user(pKarg, uarg, csmi_sas_raid_control_buffer_sz)) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              kfree(pKarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(pKarg);
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(pKarg);
++              return -ENODEV;
++      }
++
++      if (!ioc->raid_data.isRaid) {
++              pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_get_raid_control_exit;
++      }
++
++    if (pKarg->Information.uChangeCount != 0 &&
++        pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
++        pKarg->IoctlHeader.ReturnCode = 
++                      CSMI_SAS_STATUS_INVALID_PARAMETER;
++        pKarg->Information.uFailureCode = 
++                      CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
++        goto cim_get_raid_control_exit;
++    }
++
++    if (pKarg->Information.bTransformPriority != CSMI_SAS_PRIORITY_UNCHANGED) {
++        pKarg->IoctlHeader.ReturnCode = 
++                      CSMI_SAS_STATUS_INVALID_PARAMETER;
++        //pKarg->Information.uFailureCode = 
++              //      CSMI_SAS_FAIL_CODE_EXPANSION_PRIORITY_INVALID;
++    }
++    if (pKarg->Information.bRebuildPriority != CSMI_SAS_PRIORITY_AUTO &&
++        pKarg->Information.bRebuildPriority != CSMI_SAS_PRIORITY_UNCHANGED) {
++        pKarg->IoctlHeader.ReturnCode = 
++                      CSMI_SAS_STATUS_INVALID_PARAMETER;
++        pKarg->Information.uFailureCode = 
++                      CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID;
++    }
++    if (pKarg->Information.bCacheRatioFlag == CSMI_SAS_RAID_CACHE_RATIO_ENABLE) {
++        pKarg->IoctlHeader.ReturnCode = 
++                      CSMI_SAS_STATUS_INVALID_PARAMETER;
++        pKarg->Information.uFailureCode = 
++                      CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID;
++    }
++    pKarg->Information.bFailureDescription[0] = '\0';
++
++cim_get_raid_control_exit:
++
++    /*
++     * Copy the data from kernel memory to user memory
++     */
++    if (copy_to_user((char *)arg, pKarg,
++        sizeof(CSMI_SAS_RAID_CONTROL_BUFFER))) {
++        printk(KERN_ERR "%s@%d::%s() - "
++               "Unable to write out csmi_sas_get_raid_control @ %p\n",
++               __FILE__, __LINE__, __FUNCTION__, uarg);
++        kfree(pKarg);
++        return -EFAULT;
++    }
++
++    kfree(pKarg);
++
++    return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Task Managment Config command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_task_managment(unsigned long arg)
++{
++      CSMI_SAS_SSP_TASK_IU_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_SSP_TASK_IU_BUFFER      karg;
++      pSCSITaskMgmt_t                 pScsiTm;
++      pSCSITaskMgmtReply_t            pScsiTmReply;
++      MPT_ADAPTER                     *ioc = NULL;
++      MPT_SCSI_HOST                   *hd;
++      MPT_FRAME_HDR                   *mf = NULL;
++      MPIHeader_t                     *mpi_hdr;
++      int                             iocnum;
++      u8                              taskType;
++      u8                              path;
++      u8                              target;
++      u8                              lun;
++      u8                              queueTag;
++      u32                             msgContext = 0;
++      int                             retval;
++      int                             i, ii;
++      u8                              found_qtag;
++      int                             wait_timeout;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_task_managment struct @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      /* try to catch an error
++       */
++      if ((karg.Parameters.uFlags & CSMI_SAS_TASK_IU) &&
++          (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE)) {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++              goto cim_get_task_managment_exit;
++      }
++
++      if (karg.Parameters.uFlags & CSMI_SAS_TASK_IU) {
++              switch (karg.Parameters.bTaskManagementFunction) {
++
++              case CSMI_SAS_SSP_ABORT_TASK:
++                      taskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
++                      break;
++              case CSMI_SAS_SSP_ABORT_TASK_SET:
++                      taskType = MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET;
++                      break;
++              case CSMI_SAS_SSP_CLEAR_TASK_SET:
++                      taskType = MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET;
++                      break;
++              case CSMI_SAS_SSP_LOGICAL_UNIT_RESET:
++                      taskType = MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET;
++                      break;
++              case CSMI_SAS_SSP_CLEAR_ACA:
++              case CSMI_SAS_SSP_QUERY_TASK:
++              default:
++                      karg.IoctlHeader.ReturnCode =
++                          CSMI_SAS_STATUS_INVALID_PARAMETER;
++                      goto cim_get_task_managment_exit;
++              }
++      }else if (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE) {
++              /* set the code up to do a hard reset
++               */
++              taskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
++      }else {
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++              goto cim_get_task_managment_exit;
++      }
++
++      path = karg.Parameters.bPathId;
++      target = karg.Parameters.bTargetId;
++      lun = karg.Parameters.bLun;
++      queueTag = (u8)karg.Parameters.uQueueTag & 0xFF;
++
++      if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL)) {
++              karg.IoctlHeader.ReturnCode =
++                  CSMI_SAS_STATUS_INVALID_PARAMETER;
++              goto cim_get_task_managment_exit;
++      }
++      else
++              hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
++
++      switch ( karg.Parameters.uInformation ) {
++              case CSMI_SAS_SSP_TEST:
++                      dsasprintk(("TM request for test purposes\n"));
++                      break;
++              case CSMI_SAS_SSP_EXCEEDED:
++                      dsasprintk(("TM request due to timeout\n"));
++                      break;
++              case CSMI_SAS_SSP_DEMAND:
++                      dsasprintk(("TM request demanded by app\n"));
++                      break;
++              case CSMI_SAS_SSP_TRIGGER:
++                      dsasprintk(("TM request sent to trigger event\n"));
++                      break;
++      }
++
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++
++      switch (taskType) {
++
++      case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
++      /*
++       * look up qtag in the ScsiLookup[] table
++       */
++              for (i=0,found_qtag=0;i<hd->ioc->req_depth;i++) {
++                      if ((hd->ScsiLookup[i]) &&
++                          (hd->ScsiLookup[i]->tag == queueTag)) {
++                              mf = MPT_INDEX_2_MFPTR(hd->ioc, i);
++                              msgContext =
++                                  mf->u.frame.hwhdr.msgctxu.MsgContext;
++                              found_qtag=1;
++                              break;
++                      }
++              }
++
++              if(!found_qtag) {
++                      karg.IoctlHeader.ReturnCode =
++                          CSMI_SAS_STATUS_INVALID_PARAMETER;
++                      goto cim_get_task_managment_exit;
++              }
++
++      case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
++      case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
++      case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
++      /* for now, this should work
++       */
++      case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
++
++              /* Single threading ....
++               */
++              if (mptctl_set_tm_flags(hd) != 0) {
++                      karg.IoctlHeader.ReturnCode =
++                          CSMI_SAS_STATUS_FAILED;
++                      goto cim_get_task_managment_exit;
++              }
++
++              /* Send request
++               */
++              if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++                      dctlprintk((": no msg frames!\n"));
++                      mptctl_free_tm_flags(ioc);
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto cim_get_task_managment_exit;
++              }
++
++              mpi_hdr = (MPIHeader_t *) mf;
++              pScsiTm = (pSCSITaskMgmt_t ) mf;
++
++              memset(pScsiTm,0,sizeof(SCSITaskMgmt_t));
++              pScsiTm->TaskType = taskType;
++              pScsiTm->Bus = path;
++              pScsiTm->TargetID = target;
++              pScsiTm->LUN[1] = lun;
++              pScsiTm->MsgContext = mpi_hdr->MsgContext;
++              pScsiTm->TaskMsgContext = msgContext;
++              pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
++
++              ioc->ioctl->wait_done = 0;
++
++              DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
++
++              if ((retval = mpt_send_handshake_request(mptctl_id, ioc->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 cim_get_task_managment_exit;
++              }
++
++              /* Now wait for the command to complete */
++              wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout);
++              ii = wait_event_timeout(mptctl_wait,
++                   ioc->ioctl->wait_done == 1,
++                   HZ*wait_timeout);
++
++              if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++              /* Now we need to reset the board */
++                      mptctl_free_tm_flags(ioc);
++                      mpt_free_msg_frame(hd->ioc, mf);
++                      mptctl_timeout_expired(ioc->ioctl);
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto cim_get_task_managment_exit;
++              }
++
++              if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
++                      pScsiTmReply =
++                          (pSCSITaskMgmtReply_t ) ioc->ioctl->ReplyFrame;
++
++                      memset(&karg.Status,0,
++                          sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
++
++                      if(le16_to_cpu(pScsiTmReply->IOCStatus) == MPI_IOCSTATUS_SUCCESS) {
++                              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++                              karg.Status.bSSPStatus = CSMI_SAS_SSP_STATUS_COMPLETED;
++                      }else if(le16_to_cpu(pScsiTmReply->IOCStatus) ==
++                          MPI_IOCSTATUS_INSUFFICIENT_RESOURCES) {
++                              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++                              karg.Status.bSSPStatus = CSMI_SAS_SSP_STATUS_RETRY;
++                      }else {
++                              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                              karg.Status.bSSPStatus = CSMI_SAS_SSP_STATUS_FATAL_ERROR;
++                      }
++              }else{
++                      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              }
++
++              break;
++
++      default:
++              karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++              break;
++      }
++
++
++cim_get_task_managment_exit:
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++                              sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                      "Unable to write out csmi_sas_task_managment @ %p\n",
++                              __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++}
++
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*
++ *    map_sas_status_to_csmi - Conversion  for Connection Status
++ *    @mpi_sas_status: Sas status returned by the firmware
++ *
++ *    Returns converted connection status
++ *
++ */
++static u8
++map_sas_status_to_csmi(u8 mpi_sas_status)
++{
++      u8  csmi_connect_status;
++
++      switch (mpi_sas_status) {
++
++      case MPI_SASSTATUS_SUCCESS:
++              csmi_connect_status = CSMI_SAS_OPEN_ACCEPT;
++              break;
++
++      case MPI_SASSTATUS_UTC_BAD_DEST:
++              csmi_connect_status = CSMI_SAS_OPEN_REJECT_BAD_DESTINATION;
++              break;
++
++      case MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED:
++              csmi_connect_status = CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED;
++              break;
++
++      case MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED:
++              csmi_connect_status = CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED;
++              break;
++
++      case MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY:
++              csmi_connect_status = CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY;
++              break;
++
++      case MPI_SASSTATUS_UTC_WRONG_DESTINATION:
++              csmi_connect_status = CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION;
++              break;
++
++      case MPI_SASSTATUS_SDSF_NAK_RECEIVED:
++              csmi_connect_status = CSMI_SAS_OPEN_REJECT_RETRY;
++              break;
++
++      case MPI_SASSTATUS_SDSF_CONNECTION_FAILED:
++              csmi_connect_status = CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED;
++              break;
++
++      case MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT:
++              csmi_connect_status =  CSMI_SAS_OPEN_REJECT_NO_DESTINATION;
++              break;
++
++      case MPI_SASSTATUS_UNKNOWN_ERROR:
++      case MPI_SASSTATUS_INVALID_FRAME:
++      case MPI_SASSTATUS_UTC_BREAK_RECEIVED:
++      case MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST:
++      case MPI_SASSTATUS_SHORT_INFORMATION_UNIT:
++      case MPI_SASSTATUS_LONG_INFORMATION_UNIT:
++      case MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA:
++      case MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR:
++      case MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED:
++      case MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH:
++      case MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA:
++      case MPI_SASSTATUS_DATA_OFFSET_ERROR:
++              csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
++              break;
++
++      default:
++              csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
++              break;
++      }
++
++      return csmi_connect_status;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*                      mptctl_csmi_sas_phy_reset
++ *    Issues a phy link reset or phy hard reset
++ *
++ *    @ioc - Pointer to MPT_ADAPTER structure
++ *    @PhyNum - phy number
++ *    @opcode - {MPI_SAS_OP_PHY_LINK_RESET,MPI_SAS_OP_PHY_HARD_RESET}
++ *
++ *    Returns: 0 for success, non-zero error
++ */
++static int
++mptctl_csmi_sas_phy_reset(MPT_ADAPTER *ioc, u8 PhyNum, u8 opcode)
++{
++      SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
++      SasIoUnitControlReply_t         *sasIoUnitCntrReply;
++      MPT_FRAME_HDR                   *mf = NULL;
++      MPIHeader_t                     *mpi_hdr;
++      int                             ii;
++
++      if ((opcode != MPI_SAS_OP_PHY_LINK_RESET) &&
++          (opcode != MPI_SAS_OP_PHY_HARD_RESET))
++          return -1;
++
++      /* Get a MF for this command.
++       */
++      if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
++              dctlprintk((": no msg frames!\n"));
++              return -1;
++        }
++
++      mpi_hdr = (MPIHeader_t *) mf;
++      sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
++      memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
++      sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
++      sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
++      sasIoUnitCntrReq->Operation = opcode;
++      sasIoUnitCntrReq->PhyNum = PhyNum;
++
++      ioc->ioctl->wait_done = 0;
++      mpt_put_msg_frame(mptctl_id, ioc, mf);
++
++      /* Now wait for the command to complete */
++      ii = wait_event_timeout(mptctl_wait,
++           ioc->ioctl->wait_done == 1,
++           HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
++
++      if(ii <=0 && (ioc->ioctl->wait_done != 1 )) {
++              /* Now we need to reset the board */
++              mpt_free_msg_frame(ioc, mf);
++              mptctl_timeout_expired(ioc->ioctl);
++              return -1;
++      }
++
++      if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0)
++              return -1;
++
++      /* process the completed Reply Message Frame */
++      sasIoUnitCntrReply = (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame;
++      if (sasIoUnitCntrReply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
++              printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
++                  __FUNCTION__,
++                  sasIoUnitCntrReply->IOCStatus,
++                  sasIoUnitCntrReply->IOCLogInfo);
++              return -1;
++      }
++      return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Phy Control command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_phy_control(unsigned long arg)
++{
++      CSMI_SAS_PHY_CONTROL_BUFFER __user *uarg = (void __user *) arg;
++      IOCTL_HEADER                    ioctl_header;
++      PCSMI_SAS_PHY_CONTROL_BUFFER    karg;
++      SasIOUnitPage0_t                *sasIoUnitPg0=NULL;
++      dma_addr_t                      sasIoUnitPg0_dma;
++      int                             sasIoUnitPg0_data_sz=0;
++      SasIOUnitPage1_t                *sasIoUnitPg1=NULL;
++      dma_addr_t                      sasIoUnitPg1_dma;
++      int                             sasIoUnitPg1_data_sz=0;
++      ConfigExtendedPageHeader_t      hdr;
++      CONFIGPARMS                     cfg;
++      MPT_ADAPTER                     *ioc = NULL;
++      int                             iocnum;
++      int                             csmi_sas_phy_control_buffer_sz;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in IOCTL_HEADER"
++                  "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      csmi_sas_phy_control_buffer_sz = ioctl_header.Length;
++      karg = kmalloc(csmi_sas_phy_control_buffer_sz,GFP_KERNEL);
++      if(karg==NULL){
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to malloc @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__,karg);
++              return -EFAULT;
++      }
++
++      if (copy_from_user(karg, uarg, csmi_sas_phy_control_buffer_sz)) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_phy_control_buffer "
++                  "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
++              kfree(karg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(ioctl_header.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(karg);
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(karg);
++              return -ENODEV;
++      }
++
++      if (karg->bPhyIdentifier >= ioc->numPhys) {
++              karg->IoctlHeader.ReturnCode =
++                 CSMI_SAS_STATUS_INVALID_PARAMETER;
++              goto cim_sas_phy_control_exit;
++      }
++
++      /*
++       *  Retreive SAS IOUNIT PAGE 0
++       */
++
++      hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 0;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
++
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.physAddr = -1;
++      cfg.pageAddr = 0;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++      if (mpt_config(ioc, &cfg) != 0) {
++              dctlprintk((
++                  ": FAILED: READ MPI_SASIOUNITPAGE0: HEADER\n"));
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sas_phy_control_exit;
++      }
++
++      if (hdr.ExtPageLength == 0) {
++              dctlprintk((": hdr.ExtPageLength == 0\n"));
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sas_phy_control_exit;
++      }
++
++      sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
++      sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
++          sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
++
++      if (!sasIoUnitPg0) {
++              dctlprintk((": pci_alloc_consistent: FAILED\n"));
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sas_phy_control_exit;
++      }
++
++      memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
++      cfg.physAddr = sasIoUnitPg0_dma;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++      if (mpt_config(ioc, &cfg) != 0) {
++              dctlprintk((
++                  ": FAILED: READ MPI_SASIOUNITPAGE0: CURRENT\n"));
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sas_phy_control_exit;
++      }
++
++      /*
++       *  Retreive SAS IOUNIT PAGE 1
++       */
++
++      hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 1;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
++
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.physAddr = -1;
++      cfg.pageAddr = 0;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++      if (mpt_config(ioc, &cfg) != 0) {
++              dctlprintk((
++                  ": FAILED: READ MPI_SASIOUNITPAGE1: HEADER\n"));
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sas_phy_control_exit;
++      }
++
++      if (hdr.ExtPageLength == 0) {
++              dctlprintk((": hdr.ExtPageLength == 0\n"));
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sas_phy_control_exit;
++      }
++
++      sasIoUnitPg1_data_sz = hdr.ExtPageLength * 4;
++      sasIoUnitPg1 = (SasIOUnitPage1_t *) pci_alloc_consistent(ioc->pcidev,
++          sasIoUnitPg1_data_sz, &sasIoUnitPg1_dma);
++
++      if (!sasIoUnitPg1) {
++              dctlprintk((": pci_alloc_consistent: FAILED\n"));
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sas_phy_control_exit;
++      }
++
++      memset((u8 *)sasIoUnitPg1, 0, sasIoUnitPg1_data_sz);
++      cfg.physAddr = sasIoUnitPg1_dma;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++      if (mpt_config(ioc, &cfg) != 0) {
++              dctlprintk((
++                  ": FAILED:  READ MPI_SASIOUNITPAGE1: CURRENT\n"));
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++              goto cim_sas_phy_control_exit;
++      }
++
++      switch (karg->uFunction) {
++
++      case CSMI_SAS_PC_LINK_RESET:
++      case CSMI_SAS_PC_HARD_RESET:
++      {
++              u8 opcode = (karg->uFunction==CSMI_SAS_PC_LINK_RESET) ?
++                  MPI_SAS_OP_PHY_LINK_RESET : MPI_SAS_OP_PHY_HARD_RESET;
++
++              if((karg->uLinkFlags & CSMI_SAS_PHY_ACTIVATE_CONTROL) &&
++                  (karg->usLengthOfControl >= sizeof(CSMI_SAS_PHY_CONTROL)) &&
++                  (karg->bNumberOfControls > 0)){
++                      if(karg->Control[0].bRate ==
++                         CSMI_SAS_LINK_RATE_1_5_GBPS) {
++                              sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
++                              MPI_SAS_IOUNIT1_MAX_RATE_1_5 |
++                              MPI_SAS_IOUNIT1_MIN_RATE_1_5;
++                      }
++                      else if(karg->Control[0].bRate ==
++                         CSMI_SAS_LINK_RATE_3_0_GBPS) {
++                              sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
++                              MPI_SAS_IOUNIT1_MAX_RATE_3_0 |
++                              MPI_SAS_IOUNIT1_MIN_RATE_3_0;
++                      }
++                      sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags &=
++                          ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
++                      cfg.dir = 1;
++                      cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
++                      if (mpt_config(ioc, &cfg) != 0) {
++                              dctlprintk((
++                          ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
++                              karg->IoctlHeader.ReturnCode =
++                                 CSMI_SAS_STATUS_FAILED;
++                              goto cim_sas_phy_control_exit;
++                      }
++                      cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
++                      if (mpt_config(ioc, &cfg) != 0) {
++                              dctlprintk((
++                       ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
++                              karg->IoctlHeader.ReturnCode =
++                                 CSMI_SAS_STATUS_FAILED;
++                              goto cim_sas_phy_control_exit;
++                      }
++              }
++              if (mptctl_csmi_sas_phy_reset(ioc,
++                  karg->bPhyIdentifier, opcode) != 0) {
++                      dctlprintk((
++                          ": FAILED: mptctl_csmi_sas_phy_reset\n"));
++                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto cim_sas_phy_control_exit;
++              }
++              break;
++
++      }
++      case CSMI_SAS_PC_PHY_DISABLE:
++              if(karg->usLengthOfControl || karg->bNumberOfControls) {
++                      karg->IoctlHeader.ReturnCode =
++                          CSMI_SAS_STATUS_INVALID_PARAMETER;
++                      break;
++              }
++              sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags |=
++                  MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
++              cfg.dir = 1;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
++              if (mpt_config(ioc, &cfg) != 0) {
++                      dctlprintk((
++                          ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
++                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto cim_sas_phy_control_exit;
++              }
++              cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
++              if (mpt_config(ioc, &cfg) != 0) {
++                      dctlprintk((
++                          ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
++                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto cim_sas_phy_control_exit;
++              }
++              if (mptctl_csmi_sas_phy_reset(ioc,
++                  karg->bPhyIdentifier, MPI_SAS_OP_PHY_HARD_RESET) != 0) {
++                      dctlprintk((
++                          ": FAILED: mptctl_csmi_sas_phy_reset\n"));
++                      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++                      goto cim_sas_phy_control_exit;
++              }
++              break;
++
++      case CSMI_SAS_PC_GET_PHY_SETTINGS:
++              if(karg->usLengthOfControl || karg->bNumberOfControls) {
++                      karg->IoctlHeader.ReturnCode =
++                          CSMI_SAS_STATUS_INVALID_PARAMETER;
++                      break;
++              }
++              if(csmi_sas_phy_control_buffer_sz <
++                  offsetof(CSMI_SAS_PHY_CONTROL_BUFFER,Control) +
++                  (4* sizeof(CSMI_SAS_PHY_CONTROL))) {
++                      karg->IoctlHeader.ReturnCode =
++                          CSMI_SAS_STATUS_INVALID_PARAMETER;
++                      break;
++              }
++              karg->usLengthOfControl = sizeof(CSMI_SAS_PHY_CONTROL);
++              karg->bNumberOfControls = 4;
++              karg->Control[0].bType = CSMI_SAS_SAS;
++              karg->Control[0].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
++              karg->Control[1].bType = CSMI_SAS_SAS;
++              karg->Control[1].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
++              karg->Control[2].bType = CSMI_SAS_SATA;
++              karg->Control[2].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
++              karg->Control[3].bType = CSMI_SAS_SATA;
++              karg->Control[3].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++              break;
++      default:
++              break;
++      }
++
++cim_sas_phy_control_exit:
++
++      if (sasIoUnitPg0)
++              pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
++                  (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
++
++      if (sasIoUnitPg1)
++              pci_free_consistent(ioc->pcidev, sasIoUnitPg1_data_sz,
++                  (u8 *) sasIoUnitPg1, sasIoUnitPg1_dma);
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg,karg,csmi_sas_phy_control_buffer_sz)) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to write out csmi_sas_phy_control_buffer @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__, uarg);
++              kfree(karg);
++              return -EFAULT;
++      }
++
++      kfree(karg);
++      return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get Connector info command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_connector_info(unsigned long arg)
++{
++      CSMI_SAS_CONNECTOR_INFO_BUFFER __user *uarg = (void __user *) arg;
++      CSMI_SAS_CONNECTOR_INFO_BUFFER   karg;
++      MPT_ADAPTER                     *ioc = NULL;
++      int                             iocnum;
++      int                             i;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                 "Unable to read in csmi_sas_connector_info_buffer"
++                 " struct @ %p\n",
++                 __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              return -ENODEV;
++      }
++
++      karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++// TODO - to be implemented - This requires MPI changes to a Manufacturing page
++      for (i=0;i< ioc->numPhys;i++) {
++              karg.Reference[i].uPinout = CSMI_SAS_CON_UNKNOWN;
++              strcpy(karg.Reference[i].bConnector,"");
++              karg.Reference[i].bLocation = CSMI_SAS_CON_UNKNOWN;
++      }
++
++// cim_sas_get_connector_info_exit:
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, &karg,
++              sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++              "Unable to write out csmi_sas_connector_info_buffer @"
++             "%p\n",
++              __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      return 0;
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*                 mptctl_csmi_sas_fill_location_data
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ */
++static int
++mptctl_csmi_sas_fill_location_data(MPT_ADAPTER *ioc, u8 target, u8 bus, u8 opcode, CSMI_SAS_LOCATION_IDENTIFIER * location_ident)
++{
++
++      ConfigExtendedPageHeader_t      hdr;
++      CONFIGPARMS                     cfg;
++      int                             rc;
++      SasDevicePage0_t                *sasDevicePg0=NULL;
++      SasEnclosurePage0_t             *sasEnclosurePg0=NULL;
++      dma_addr_t                      sasDevicePg0_dma,sasEnclosurePg0_dma;
++      int                             sasDevicePg0_data_sz=0;
++      int                             sasEnclosurePg0_data_sz=0;
++      u64                             SASAddress64;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      /* SAS Device Page 0 */
++      hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 0;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
++
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.physAddr = -1;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              rc=-1;
++              goto fill_location_data_exit;
++      }
++
++      if (hdr.ExtPageLength == 0) {
++              rc=-1;
++              goto fill_location_data_exit;
++      }
++
++      sasDevicePg0_data_sz = hdr.ExtPageLength * 4;
++      sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent(
++          ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma);
++      if (!sasDevicePg0) {
++              rc=-1;
++              goto fill_location_data_exit;
++      }
++
++      memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz);
++      cfg.physAddr = sasDevicePg0_dma;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++      cfg.pageAddr = (bus << 8) + target
++          + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
++              MPI_SAS_DEVICE_PGAD_FORM_SHIFT);
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              rc=-1;
++              goto fill_location_data_exit;
++      }
++
++      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_ADDRESS_VALID;
++      SASAddress64 = reverse_byte_order64((u64 *)&sasDevicePg0->SASAddress);
++      memcpy(&location_ident->bSASAddress,&SASAddress64,sizeof(u64));
++
++      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_LUN_VALID;
++      memset(location_ident->bSASLun, 0, sizeof(location_ident->bSASLun));
++
++      /* SAS Enclosure Page 0 */
++      hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 0;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
++
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.physAddr = -1;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              rc=0;
++              goto fill_location_data_exit;
++      }
++
++      if (hdr.ExtPageLength == 0) {
++              rc=0;
++              goto fill_location_data_exit;
++      }
++
++      sasEnclosurePg0_data_sz = hdr.ExtPageLength * 4;
++      sasEnclosurePg0 = (SasEnclosurePage0_t *) pci_alloc_consistent(
++          ioc->pcidev, sasEnclosurePg0_data_sz, &sasEnclosurePg0_dma);
++      if (!sasEnclosurePg0) {
++              rc=0;
++              goto fill_location_data_exit;
++      }
++      cfg.physAddr = sasEnclosurePg0_dma;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++      cfg.pageAddr = le16_to_cpu(sasDevicePg0->EnclosureHandle)
++          + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
++          MPI_SAS_ENCLOS_PGAD_FORM_SHIFT);
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              rc=0;
++              goto fill_location_data_exit;
++      }
++
++      location_ident->bLocationFlags |=
++          CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID;
++      SASAddress64 = reverse_byte_order64(
++          (u64 *)&sasEnclosurePg0->EnclosureLogicalID);
++      if (SASAddress64)
++              memcpy(&location_ident->bEnclosureIdentifier,
++                  &SASAddress64,sizeof(u64));
++      else
++              strcpy(location_ident->bEnclosureIdentifier,"Internal");
++
++// bBayPrefix - not supported
++
++// TODO - We need to look at sasEnclosurePg0-.Flags , to determine
++//    whether SEP BUS/TargetID is valid.  Ifs its a SES device, then
++//    issue internal inquiry to (bus/target) to gather the Enclosure name.
++//    If the device is SMP, then issue SMP_MANUFACTURING to get enclosure name
++//    If its direct attached, there is no enclosure name
++      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID;
++      strcpy(location_ident->bEnclosureName,"Not Supported");
++
++      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_LOCATION_STATE_VALID;
++      location_ident->bLocationState = CSMI_SAS_LOCATE_UNKNOWN;
++
++      location_ident->bLocationFlags |= CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID;
++      location_ident->bBayIdentifier = le16_to_cpu(sasDevicePg0->Slot);
++
++
++// TODO - illuminating LEDs,
++// karg->bIdentify = CSMI_SAS_LOCATE_FORCE_OFF, CSMI_SAS_LOCATE_FORCE_ON
++// We can enable/disable LEDs by SCSI Enclosure Processor MPI request message
++// printk("Flags=0x%x\n",sasEnclosurePg0->Flags);
++
++/* check sasEnclosurePg0->Flags -
++ * to validate whether we need to send the SEPRequest
++ * bit:5 should be set
++ * bit:3-0 any bit should be set.  If zero, then SEPRequest will fail
++*/
++
++/* MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR
++ * Look in mpi_init.h
++ * SEPRequest_t = structure
++ *
++ * SEPRequest_t->Action should be set to MPI_SEP_REQ_ACTION_WRITE_STATUS
++ *
++ * SEPRequest_t->Flags should be set to
++ * MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS, to pass along enclosure/slot ids
++ *
++ * SEPRequest_t->SlotStatus |= MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST - this
++ * will illuminate the LEDs
++ */
++
++fill_location_data_exit:
++
++      if (sasDevicePg0 != NULL)
++              pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
++                  sasDevicePg0, sasDevicePg0_dma);
++
++      if (sasEnclosurePg0 != NULL)
++              pci_free_consistent(ioc->pcidev, sasEnclosurePg0_data_sz,
++                  sasEnclosurePg0, sasEnclosurePg0_dma);
++      return rc;
++}
++
++
++static int
++mptctl_csmi_sas_fill_location_data_raid(MPT_ADAPTER *ioc, PCSMI_SAS_GET_LOCATION_BUFFER karg, u8 volumeID, u8 VolumeBus)
++{
++      pRaidVolumePage0_t              pVolume0 = NULL;
++      pRaidPhysDiskPage0_t            pPhysDisk0 = NULL;
++      CONFIGPARMS                     cfg;
++      ConfigPageHeader_t              header;
++      u8                              physDiskNumMax,physDiskNum;
++      int                             volumepage0sz = 0, physdiskpage0sz = 0;
++      dma_addr_t                      volume0_dma, physdisk0_dma;
++      int                             csmi_sas_get_location_sz;
++      int                             rc = 0,i;
++
++      csmi_sas_get_location_sz = karg->IoctlHeader.Length;
++      physDiskNumMax = (csmi_sas_get_location_sz -
++          offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location))
++          / sizeof(CSMI_SAS_LOCATION_IDENTIFIER);
++      karg->bNumberOfLocationIdentifiers=0;
++
++      /*
++       * get RAID Volume Page 0
++       */
++
++      header.PageVersion = 0;
++      header.PageLength = 0;
++      header.PageNumber = 0;
++      header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
++      cfg.cfghdr.hdr = &header;
++      cfg.physAddr = -1;
++      cfg.pageAddr = (VolumeBus << 8) + volumeID;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++      if (mpt_config(ioc, &cfg) != 0) {
++              rc = -1;
++              goto sas_fill_location_data_raid_exit;
++      }
++
++      if (header.PageLength == 0) {
++              rc = -1;
++              goto sas_fill_location_data_raid_exit;
++      }
++
++      volumepage0sz = header.PageLength * 4;
++      pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
++          &volume0_dma);
++      if (!pVolume0) {
++              rc = -1;
++              goto sas_fill_location_data_raid_exit;
++      }
++
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++      cfg.physAddr = volume0_dma;
++      if (mpt_config(ioc, &cfg) != 0){
++              rc = -1;
++              goto sas_fill_location_data_raid_exit;
++      }
++
++
++      /*
++       * get RAID Physical Disk Page 0
++       */
++      header.PageVersion = 0;
++      header.PageLength = 0;
++      header.PageNumber = 0;
++      header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
++      cfg.cfghdr.hdr = &header;
++      cfg.physAddr = -1;
++      cfg.pageAddr = 0;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;
++      cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
++      if (mpt_config(ioc, &cfg) != 0) {
++              rc = -1;
++              goto sas_fill_location_data_raid_exit;
++      }
++
++      if (header.PageLength == 0) {
++              rc = -1;
++              goto sas_fill_location_data_raid_exit;
++      }
++
++      physdiskpage0sz = header.PageLength * 4;
++      pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
++          &physdisk0_dma);
++      if (!pPhysDisk0) {
++              rc = -1;
++              goto sas_fill_location_data_raid_exit;
++      }
++      cfg.physAddr = physdisk0_dma;
++
++      for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
++
++              physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++              cfg.pageAddr = physDiskNum;
++              if (mpt_config(ioc, &cfg) != 0){
++                      rc = -1;
++                      goto sas_fill_location_data_raid_exit;
++              }
++
++              if((mptctl_csmi_sas_fill_location_data(ioc,
++                 pPhysDisk0->PhysDiskID,
++                 karg->bPathId, karg->bIdentify,
++                 &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
++                      karg->bNumberOfLocationIdentifiers++;
++      }
++
++
++sas_fill_location_data_raid_exit:
++
++      if (pVolume0 != NULL)
++              pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
++                  volume0_dma);
++
++      if(pPhysDisk0 != NULL)
++              pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
++                  physdisk0_dma);
++
++      return rc;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* Prototype Routine for the CSMI SAS Get location command.
++ *
++ * Outputs:   None.
++ * Return:    0 if successful
++ *            -EFAULT if data unavailable
++ *            -ENODEV if no such device/adapter
++ */
++static int
++mptctl_csmi_sas_get_location(unsigned long arg)
++{
++      CSMI_SAS_GET_LOCATION_BUFFER __user *uarg = (void __user *) arg;
++      PCSMI_SAS_GET_LOCATION_BUFFER   karg;
++      IOCTL_HEADER                    ioctl_header;
++      MPT_ADAPTER                     *ioc = NULL;
++      int                             iocnum,i;
++      int                             csmi_sas_get_location_sz;
++
++      dctlprintk((": %s called.\n",__FUNCTION__));
++
++      if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in IOCTL_HEADER"
++                  "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      csmi_sas_get_location_sz = ioctl_header.Length;
++      karg = kmalloc(csmi_sas_get_location_sz,GFP_KERNEL);
++      if(karg==NULL){
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to malloc @ %p\n",
++                  __FILE__, __LINE__, __FUNCTION__,karg);
++              return -EFAULT;
++      }
++
++      if (copy_from_user(karg, uarg, csmi_sas_get_location_sz)) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to read in csmi_sas_phy_control_buffer "
++                  "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
++              kfree(karg);
++              return -EFAULT;
++      }
++
++      if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
++          &ioc)) < 0) || (ioc == NULL)) {
++              dctlprintk((KERN_ERR
++              "%s::%s() @%d - ioc%d not found!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(karg);
++              return -ENODEV;
++      }
++
++      if (!mptctl_is_this_sas_cntr(ioc)) {
++              dctlprintk((KERN_ERR
++                  "%s::%s() @%d - ioc%d not SAS controller!\n",
++                  __FILE__, __FUNCTION__, __LINE__, iocnum));
++              kfree(karg);
++              return -ENODEV;
++      }
++
++      karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
++      if(karg->bLengthOfLocationIdentifier != sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
++              goto cim_sas_get_location_exit;
++
++
++      /* RAID SUPPORT */
++      if (ioc->raid_data.isRaid && ioc->raid_data.pIocPg2) {
++              for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){
++                      if (karg->bTargetId ==
++                          ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) {
++                              if(mptctl_csmi_sas_fill_location_data_raid(ioc, karg,
++                                  ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID,
++                                  ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus) == 0)
++                                      karg->IoctlHeader.ReturnCode =
++                                          CSMI_SAS_STATUS_SUCCESS;
++                              else
++                                      karg->IoctlHeader.ReturnCode =
++                                          CSMI_SAS_STATUS_FAILED;
++                              goto cim_sas_get_location_exit;
++                      }
++              }
++      }
++
++      /* NON-RAID SUPPORT */
++
++      /* make sure there's enough room to populate the Location[] struct */
++      if ((csmi_sas_get_location_sz -
++          offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) <
++          sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
++              goto cim_sas_get_location_exit;
++
++      karg->bNumberOfLocationIdentifiers=1; 
++      karg->Location[0].bLocationFlags=0;
++      if((mptctl_csmi_sas_fill_location_data(ioc, karg->bTargetId,
++                 karg->bPathId, karg->bIdentify, &karg->Location[0])) == 0)
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
++      else
++              karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
++
++cim_sas_get_location_exit:
++
++      /* Copy the data from kernel memory to user memory
++       */
++      if (copy_to_user((char *)arg, karg, csmi_sas_get_location_sz)) {
++              printk(KERN_ERR "%s@%d::%s() - "
++                  "Unable to write out csmi_sas_get_location_buffer "
++                  "@ %p\n",__FILE__, __LINE__, __FUNCTION__, uarg);
++              return -EFAULT;
++      }
++
++      kfree(karg);
++      return 0;
++}
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.h linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.h        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.h       2007-11-02 09:10:23.000000000 +0100
+@@ -0,0 +1,1796 @@
++/**************************************************************************
++
++Module Name:
++
++   CSMISAS.H
++
++
++Abstract:
++
++   This file contains constants and data structure definitions used by drivers
++   that support the Common Storage Management Interface specification for
++   SAS or SATA in either the Windows or Linux.
++
++   This should be considered as a reference implementation only.  Changes may 
++   be necessary to accommodate a specific build environment or target OS.
++
++Revision History:
++
++   001  SEF   8/12/03  Initial release.
++   002  SEF   8/20/03  Cleanup to match documentation.
++   003  SEF   9/12/03  Additional cleanup, created combined header
++   004  SEF   9/23/03  Changed base types to match linux defaults
++                       Added RAID signature
++                       Added bControllerFlags to CSMI_SAS_CNTLR_CONFIG
++                       Changed CSMI_SAS_BEGIN_PACK to 8 for common structures
++                       Fixed other typos identified in first compilation test
++   005  SEF  10/03/03  Additions to match first version of CSMI document
++   006  SEF  10/14/03  Fixed typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER
++                       Added defines for bConnectionRate
++   007  SEF  10/15/03  Added Firmware Download Control Code and support
++                       Added CSMI revision support
++   008  SEF  10/30/03  No functional change, just updated version to track
++                       spec changes
++   009  SEF  12/09/03  No functional change, just updated version to track
++                       spec changes
++   010  SEF   3/11/04  Fixed typedef struct CSMI_SAS_RAID_DRIVES to include the
++                       bFirmware member that is defined in the spec, but
++                       was missing in this file,
++                       added CC_CSMI_SAS_TASK_MANAGEMENT
++   011  SEF   4/02/04  No functional change, added comment line before
++                       CC_CSMI_SAS_TASK_MANAGEMENT
++   012  SEF   4/16/04  Added IOControllerNumber to linux header,
++                       Modified linux control codes to have upper word of
++                       0xCC77.... to indicate CSMI version 77
++                       Added bSignalClass to CC_CSMI_SET_PHY_INFO
++                       Added CC_CSMI_SAS_PHY_CONTROL support
++   013  SEF   5/14/04  Added CC_CSMI_SAS_GET_CONNECTOR_INFO support
++   014  SEF   5/24/04  No functional change, just updated version to track spec
++                       changes
++   015  SEF   6/16/04  changed bPinout to uPinout to reflect proper size,
++                       changed width of bLocation defines to reflect size
++   016  SEF   6/17/04  changed bLengthOfControls in CSMI_SAS_PHY_CONTROL
++                       to be proper size
++   017  SEF   9/17/04  added CSMI_SAS_SATA_PORT_SELECTOR,
++                       CSMI_SAS_LINK_VIRTUAL, CSMI_SAS_CON_NOT_PRESENT, and
++                       CSMI_SAS_CON_NOT_CONNECTED
++   018  SEF   9/20/04  added CSMI_SAS_PHY_USER_PATTERN, 
++                       changed definition of CSMI_SAS_PHY_FIXED_PATTERN to not
++                       conflict with activate definition
++   019  SEF  12/06/04  added CSMI_SAS_GET_LOCATION
++                       added bSSPStatus to CSMI_SAS_SSP_PASSTHRU_STATUS 
++                       structure
++   020  SEF   5/25/05  added CSMI_SAS_PHY_VIRTUAL_SMP, and changes to 
++                       CSMI_SAS_GET_LOCATION
++   021  SEF  11/03/05  added new RAID creation functionality 
++   022  SEF   2/01/06  corrected typo bNegotitiatedLInkRate
++                       Added two more RAID_TYPES, 7 and 8
++   023  SEF   4/04/06  added CSMI_RAID_TYPE_1E
++                       changed structures that contained surface scan
++                       to priority approach rather than time, causes
++                       0.89 to incompatible with 0.87, so a version 
++                       check is necessary when interpreting the 
++                       raid structures
++                       Added netware section
++
++**************************************************************************/
++
++#ifndef _CSMI_SAS_H_
++#define _CSMI_SAS_H_
++
++// CSMI Specification Revision, the intent is that all versions of the
++// specification will be backward compatible after the 1.00 release.
++// Major revision number, corresponds to xxxx. of CSMI specification
++// Minor revision number, corresponds to .xxxx of CSMI specification
++#define CSMI_MAJOR_REVISION   0
++#define CSMI_MINOR_REVISION   89
++
++/*************************************************************************/
++/* PATCHES FOR TYPOS                                                     */
++/*************************************************************************/
++
++#define bNegotitiatedLInkRate bNegotiatedLinkRate
++
++/*************************************************************************/
++/* TARGET OS LINUX SPECIFIC CODE                                         */
++/*************************************************************************/
++
++// EDM #ifdef _linux
++#ifdef __KERNEL__
++
++// Linux base types
++
++#include <linux/types.h>
++
++#define __i8    char
++
++// pack definition
++
++// EDM #define CSMI_SAS_BEGIN_PACK(x)    pack(x)
++// EDM #define CSMI_SAS_END_PACK         pack()
++
++// IOCTL Control Codes
++// (IoctlHeader.ControlCode)
++
++// Control Codes prior to 0.77
++
++// Control Codes requiring CSMI_ALL_SIGNATURE
++
++// #define CC_CSMI_SAS_GET_DRIVER_INFO    0x12345678
++// #define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x23456781
++// #define CC_CSMI_SAS_GET_CNTLR_STATUS   0x34567812
++// #define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x92345678
++
++// Control Codes requiring CSMI_RAID_SIGNATURE
++
++// #define CC_CSMI_SAS_GET_RAID_INFO      0x45678123
++// #define CC_CSMI_SAS_GET_RAID_CONFIG    0x56781234
++
++// Control Codes requiring CSMI_SAS_SIGNATURE
++
++// #define CC_CSMI_SAS_GET_PHY_INFO       0x67812345
++// #define CC_CSMI_SAS_SET_PHY_INFO       0x78123456
++// #define CC_CSMI_SAS_GET_LINK_ERRORS    0x81234567
++// #define CC_CSMI_SAS_SMP_PASSTHRU       0xA1234567
++// #define CC_CSMI_SAS_SSP_PASSTHRU       0xB1234567
++// #define CC_CSMI_SAS_STP_PASSTHRU       0xC1234567
++// #define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xD1234567
++// #define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xE1234567
++// #define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xF1234567
++// #define CC_CSMI_SAS_TASK_MANAGEMENT    0xA2345678
++
++// Control Codes for 0.77 and later
++
++// Control Codes requiring CSMI_ALL_SIGNATURE
++
++#define CC_CSMI_SAS_GET_DRIVER_INFO    0xCC770001
++#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0xCC770002
++#define CC_CSMI_SAS_GET_CNTLR_STATUS   0xCC770003
++#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0xCC770004
++
++// Control Codes requiring CSMI_RAID_SIGNATURE
++
++#define CC_CSMI_SAS_GET_RAID_INFO      0xCC77000A
++#define CC_CSMI_SAS_GET_RAID_CONFIG    0xCC77000B
++#define CC_CSMI_SAS_GET_RAID_FEATURES  0xCC77000C
++#define CC_CSMI_SAS_SET_RAID_CONTROL   0xCC77000D
++#define CC_CSMI_SAS_GET_RAID_ELEMENT   0xCC77000E
++#define CC_CSMI_SAS_SET_RAID_OPERATION 0xCC77000F
++
++// Control Codes requiring CSMI_SAS_SIGNATURE
++
++#define CC_CSMI_SAS_GET_PHY_INFO       0xCC770014
++#define CC_CSMI_SAS_SET_PHY_INFO       0xCC770015
++#define CC_CSMI_SAS_GET_LINK_ERRORS    0xCC770016
++#define CC_CSMI_SAS_SMP_PASSTHRU       0xCC770017
++#define CC_CSMI_SAS_SSP_PASSTHRU       0xCC770018
++#define CC_CSMI_SAS_STP_PASSTHRU       0xCC770019
++#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xCC770020
++#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xCC770021
++#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xCC770022
++#define CC_CSMI_SAS_TASK_MANAGEMENT    0xCC770023
++#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0xCC770024
++#define CC_CSMI_SAS_GET_LOCATION       0xCC770025
++
++
++// Control Codes requiring CSMI_PHY_SIGNATURE
++
++#define CC_CSMI_SAS_PHY_CONTROL        0xCC77003C
++
++// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
++#pragma pack(8)
++
++// IOCTL_HEADER
++typedef struct _IOCTL_HEADER {
++   __u32 IOControllerNumber;
++    __u32 Length;
++    __u32 ReturnCode;
++    __u32 Timeout;
++    __u16 Direction;
++} IOCTL_HEADER, 
++  *PIOCTL_HEADER;
++
++// EDM #pragma CSMI_SAS_END_PACK
++#pragma pack()
++
++#endif
++
++/*************************************************************************/
++/* TARGET OS WINDOWS SPECIFIC CODE                                       */
++/*************************************************************************/
++
++#ifdef _WIN32
++
++// windows IOCTL definitions
++
++#ifndef _NTDDSCSIH_
++#include <ntddscsi.h>
++#endif
++
++// pack definition
++
++#if defined _MSC_VER
++   #define CSMI_SAS_BEGIN_PACK(x)    pack(push,x)
++   #define CSMI_SAS_END_PACK         pack(pop)
++#elif defined __BORLANDC__
++   #define CSMI_SAS_BEGIN_PACK(x)    option -a##x
++   #define CSMI_SAS_END_PACK         option -a.
++#else
++   #error "CSMISAS.H - Must externally define a pack compiler designator."
++#endif
++
++// base types
++
++#define __u8    unsigned char
++#define __u16   unsigned short
++#define __u32   unsigned long
++#define __u64   unsigned __int64
++
++#define __i8    char
++
++// IOCTL Control Codes
++// (IoctlHeader.ControlCode)
++
++// Control Codes requiring CSMI_ALL_SIGNATURE
++
++#define CC_CSMI_SAS_GET_DRIVER_INFO    1
++#define CC_CSMI_SAS_GET_CNTLR_CONFIG   2
++#define CC_CSMI_SAS_GET_CNTLR_STATUS   3
++#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  4
++
++// Control Codes requiring CSMI_RAID_SIGNATURE
++
++#define CC_CSMI_SAS_GET_RAID_INFO      10
++#define CC_CSMI_SAS_GET_RAID_CONFIG    11
++#define CC_CSMI_SAS_GET_RAID_FEATURES  12
++#define CC_CSMI_SAS_SET_RAID_CONTROL   13
++#define CC_CSMI_SAS_GET_RAID_ELEMENT   14
++#define CC_CSMI_SAS_SET_RAID_OPERATION 15
++
++// Control Codes requiring CSMI_SAS_SIGNATURE
++
++#define CC_CSMI_SAS_GET_PHY_INFO       20
++#define CC_CSMI_SAS_SET_PHY_INFO       21
++#define CC_CSMI_SAS_GET_LINK_ERRORS    22
++#define CC_CSMI_SAS_SMP_PASSTHRU       23
++#define CC_CSMI_SAS_SSP_PASSTHRU       24
++#define CC_CSMI_SAS_STP_PASSTHRU       25
++#define CC_CSMI_SAS_GET_SATA_SIGNATURE 26
++#define CC_CSMI_SAS_GET_SCSI_ADDRESS   27
++#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 28
++#define CC_CSMI_SAS_TASK_MANAGEMENT    29
++#define CC_CSMI_SAS_GET_CONNECTOR_INFO 30
++#define CC_CSMI_SAS_GET_LOCATION       31
++
++// Control Codes requiring CSMI_PHY_SIGNATURE
++
++#define CC_CSMI_SAS_PHY_CONTROL        60
++
++#define IOCTL_HEADER SRB_IO_CONTROL
++#define PIOCTL_HEADER PSRB_IO_CONTROL
++
++#endif
++
++/*************************************************************************/
++/* TARGET OS NETWARE SPECIFIC CODE                                       */
++/*************************************************************************/
++
++#ifdef _NETWARE
++
++// NetWare IOCTL definitions
++
++#define CSMI_SAS_BEGIN_PACK(x)    pack(x)
++#define CSMI_SAS_END_PACK         pack()
++
++#ifndef LONG
++typedef unsigned long LONG;
++#endif
++
++#ifndef WORD
++typedef unsigned short WORD;
++#endif
++
++#ifndef BYTE
++typedef unsigned char BYTE;
++#endif
++
++/* Need to have these definitions for Netware */
++#define __u8    unsigned char
++#define __u16   unsigned short
++#define __u32   unsigned long
++#define __u64   unsigned __int64
++
++#define __i8    char
++
++
++#pragma CSMI_SAS_BEGIN_PACK(8)
++
++// IOCTL_HEADER
++typedef struct _IOCTL_HEADER {
++    __u32 Length;
++    __u32 ReturnCode;
++} IOCTL_HEADER, 
++  *PIOCTL_HEADER;
++
++#pragma CSMI_SAS_END_PACK
++
++// IOCTL Control Codes
++// (IoctlHeader.ControlCode)
++
++// Control Codes requiring CSMI_ALL_SIGNATURE
++
++#define CC_CSMI_SAS_GET_DRIVER_INFO    0x01FF0001
++#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x01FF0002
++#define CC_CSMI_SAS_GET_CNTLR_STATUS   0x01FF0003
++#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x01FF0004
++
++// Control Codes requiring CSMI_RAID_SIGNATURE
++
++#define CC_CSMI_SAS_GET_RAID_INFO      0x01FF000A
++#define CC_CSMI_SAS_GET_RAID_CONFIG    0x01FF000B
++#define CC_CSMI_SAS_GET_RAID_FEATURES  0x01FF000C
++#define CC_CSMI_SAS_SET_RAID_CONTROL   0x01FF000D
++#define CC_CSMI_SAS_GET_RAID_ELEMENT   0x01FF000E
++#define CC_CSMI_SAS_SET_RAID_OPERATION 0x01FF000F
++
++// Control Codes requiring CSMI_SAS_SIGNATURE
++
++#define CC_CSMI_SAS_GET_PHY_INFO       0x01FF0014
++#define CC_CSMI_SAS_SET_PHY_INFO       0x01FF0015
++#define CC_CSMI_SAS_GET_LINK_ERRORS    0x01FF0016
++#define CC_CSMI_SAS_SMP_PASSTHRU       0x01FF0017
++#define CC_CSMI_SAS_SSP_PASSTHRU       0x01FF0018
++#define CC_CSMI_SAS_STP_PASSTHRU       0x01FF0019
++#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0x01FF001A
++#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0x01FF001B
++#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0x01FF001C
++#define CC_CSMI_SAS_TASK_MANAGEMENT    0x01FF001D
++#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0x01FF001E
++#define CC_CSMI_SAS_GET_LOCATION       0x01FF001F
++
++// Control Codes requiring CSMI_PHY_SIGNATURE
++
++#define CC_CSMI_SAS_PHY_CONTROL        60
++
++#endif
++
++/*************************************************************************/
++/* TARGET OS NOT DEFINED ERROR                                           */
++/*************************************************************************/
++
++// EDM #if (!_WIN32 && !_linux && !_NETWARE)
++//#if (!_WIN32 && !__KERNEL__ && !_NETWARE)
++//   #error "Unknown target OS."
++//#endif
++
++/*************************************************************************/
++/* OS INDEPENDENT CODE                                                   */
++/*************************************************************************/
++
++/* * * * * * * * * * Class Independent IOCTL Constants * * * * * * * * * */
++
++// Return codes for all IOCTL's regardless of class
++// (IoctlHeader.ReturnCode)
++
++#define CSMI_SAS_STATUS_SUCCESS              0
++#define CSMI_SAS_STATUS_FAILED               1
++#define CSMI_SAS_STATUS_BAD_CNTL_CODE        2
++#define CSMI_SAS_STATUS_INVALID_PARAMETER    3
++#define CSMI_SAS_STATUS_WRITE_ATTEMPTED      4
++
++// Signature value
++// (IoctlHeader.Signature)
++
++#define CSMI_ALL_SIGNATURE    "CSMIALL"
++
++// Timeout value default of 60 seconds
++// (IoctlHeader.Timeout)
++
++#define CSMI_ALL_TIMEOUT      60
++
++//  Direction values for data flow on this IOCTL
++// (IoctlHeader.Direction, Linux only)
++#define CSMI_SAS_DATA_READ    0
++#define CSMI_SAS_DATA_WRITE   1
++
++// I/O Bus Types
++// ISA and EISA bus types are not supported
++// (bIoBusType)
++
++#define CSMI_SAS_BUS_TYPE_PCI       3
++#define CSMI_SAS_BUS_TYPE_PCMCIA    4
++
++// Controller Status
++// (uStatus)
++
++#define CSMI_SAS_CNTLR_STATUS_GOOD     1
++#define CSMI_SAS_CNTLR_STATUS_FAILED   2
++#define CSMI_SAS_CNTLR_STATUS_OFFLINE  3
++#define CSMI_SAS_CNTLR_STATUS_POWEROFF 4
++
++// Offline Status Reason
++// (uOfflineReason)
++
++#define CSMI_SAS_OFFLINE_REASON_NO_REASON             0
++#define CSMI_SAS_OFFLINE_REASON_INITIALIZING          1
++#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_DEGRADED 2
++#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_FAILURE  3
++
++// Controller Class
++// (bControllerClass)
++
++#define CSMI_SAS_CNTLR_CLASS_HBA    5
++
++// Controller Flag bits
++// (uControllerFlags)
++
++#define CSMI_SAS_CNTLR_SAS_HBA   0x00000001
++#define CSMI_SAS_CNTLR_SAS_RAID  0x00000002
++#define CSMI_SAS_CNTLR_SATA_HBA  0x00000004
++#define CSMI_SAS_CNTLR_SATA_RAID 0x00000008
++
++// for firmware download
++#define CSMI_SAS_CNTLR_FWD_SUPPORT  0x00010000
++#define CSMI_SAS_CNTLR_FWD_ONLINE   0x00020000
++#define CSMI_SAS_CNTLR_FWD_SRESET   0x00040000
++#define CSMI_SAS_CNTLR_FWD_HRESET   0x00080000
++#define CSMI_SAS_CNTLR_FWD_RROM     0x00100000
++
++// for RAID configuration supported
++#define CSMI_SAS_CNTLR_RAID_CFG_SUPPORT  0x010000
++
++// Download Flag bits
++// (uDownloadFlags)
++#define CSMI_SAS_FWD_VALIDATE       0x00000001
++#define CSMI_SAS_FWD_SOFT_RESET     0x00000002
++#define CSMI_SAS_FWD_HARD_RESET     0x00000004
++
++// Firmware Download Status
++// (usStatus)
++#define CSMI_SAS_FWD_SUCCESS        0
++#define CSMI_SAS_FWD_FAILED         1
++#define CSMI_SAS_FWD_USING_RROM     2
++#define CSMI_SAS_FWD_REJECT         3
++#define CSMI_SAS_FWD_DOWNREV        4
++
++// Firmware Download Severity
++// (usSeverity>
++#define CSMI_SAS_FWD_INFORMATION    0
++#define CSMI_SAS_FWD_WARNING        1
++#define CSMI_SAS_FWD_ERROR          2
++#define CSMI_SAS_FWD_FATAL          3
++
++/* * * * * * * * * * SAS RAID Class IOCTL Constants  * * * * * * * * */
++
++// Return codes for the RAID IOCTL's regardless of class
++// (IoctlHeader.ReturnCode)
++
++#define CSMI_SAS_RAID_SET_OUT_OF_RANGE       1000
++#define CSMI_SAS_RAID_SET_BUFFER_TOO_SMALL   1001
++#define CSMI_SAS_RAID_SET_DATA_CHANGED       1002
++
++// Signature value
++// (IoctlHeader.Signature)
++
++#define CSMI_RAID_SIGNATURE    "CSMIARY"
++
++// Timeout value default of 60 seconds
++// (IoctlHeader.Timeout)
++
++#define CSMI_RAID_TIMEOUT      60
++
++// RAID Types
++// (bRaidType)
++#define CSMI_SAS_RAID_TYPE_NONE     0
++#define CSMI_SAS_RAID_TYPE_0        1
++#define CSMI_SAS_RAID_TYPE_1        2
++#define CSMI_SAS_RAID_TYPE_10       3
++#define CSMI_SAS_RAID_TYPE_5        4
++#define CSMI_SAS_RAID_TYPE_15       5
++#define CSMI_SAS_RAID_TYPE_6        6
++#define CSMI_SAS_RAID_TYPE_50       7
++#define CSMI_SAS_RAID_TYPE_VOLUME   8
++#define CSMI_SAS_RAID_TYPE_1E       9
++#define CSMI_SAS_RAID_TYPE_OTHER    255
++// the last value 255 was already defined for other
++// so end is defined as 254
++#define CSMI_SAS_RAID_TYPE_END      254
++
++// RAID Status
++// (bStatus)
++#define CSMI_SAS_RAID_SET_STATUS_OK             0
++#define CSMI_SAS_RAID_SET_STATUS_DEGRADED       1
++#define CSMI_SAS_RAID_SET_STATUS_REBUILDING     2
++#define CSMI_SAS_RAID_SET_STATUS_FAILED         3
++#define CSMI_SAS_RAID_SET_STATUS_OFFLINE        4
++#define CSMI_SAS_RAID_SET_STATUS_TRANSFORMING   5
++#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_REBUILD         6
++#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_TRANSFORMATION  7
++
++// RAID Drive Count
++// (bDriveCount, 0xF1 to 0xFF are reserved)
++#define CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG   0xF1
++#define CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED 0xF2
++
++// RAID Data Type
++// (bDataType)
++#define CSMI_SAS_RAID_DATA_DRIVES           0
++#define CSMI_SAS_RAID_DATA_DEVICE_ID        1
++#define CSMI_SAS_RAID_DATA_ADDITIONAL_DATA  2
++
++// RAID Drive Status
++// (bDriveStatus)
++#define CSMI_SAS_DRIVE_STATUS_OK          0
++#define CSMI_SAS_DRIVE_STATUS_REBUILDING  1
++#define CSMI_SAS_DRIVE_STATUS_FAILED      2
++#define CSMI_SAS_DRIVE_STATUS_DEGRADED    3
++#define CSMI_SAS_DRIVE_STATUS_OFFLINE     4
++#define CSMI_SAS_DRIVE_STATUS_QUEUED_FOR_REBUILD 5
++
++// RAID Drive Usage
++// (bDriveUsage)
++#define CSMI_SAS_DRIVE_CONFIG_NOT_USED      0
++#define CSMI_SAS_DRIVE_CONFIG_MEMBER        1
++#define CSMI_SAS_DRIVE_CONFIG_SPARE         2
++#define CSMI_SAS_DRIVE_CONFIG_SPARE_ACTIVE  3
++
++// RAID Drive Type
++// (bDriveType)
++#define CSMI_SAS_DRIVE_TYPE_UNKNOWN         0
++#define CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS 1
++#define CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS   2
++#define CSMI_SAS_DRIVE_TYPE_SATA            3
++#define CSMI_SAS_DRIVE_TYPE_SATA_PS         4
++#define CSMI_SAS_DRIVE_TYPE_OTHER           255
++
++// RAID Write Protect
++// (bWriteProtect)
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN     0
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNCHANGED   0
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_ENABLED     1
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_DISABLED    2
++
++// RAID Cache Setting
++// (bCacheSetting)
++#define CSMI_SAS_RAID_SET_CACHE_UNKNOWN             0
++#define CSMI_SAS_RAID_SET_CACHE_UNCHANGED           0
++#define CSMI_SAS_RAID_SET_CACHE_ENABLED             1
++#define CSMI_SAS_RAID_SET_CACHE_DISABLED            2
++#define CSMI_SAS_RAID_SET_CACHE_CORRUPT             3
++
++// RAID Features
++// (uFeatures)
++#define CSMI_SAS_RAID_FEATURE_TRANSFORMATION    0x00000001
++#define CSMI_SAS_RAID_FEATURE_REBUILD           0x00000002
++#define CSMI_SAS_RAID_FEATURE_SPLIT_MIRROR      0x00000004
++#define CSMI_SAS_RAID_FEATURE_MERGE_MIRROR      0x00000008
++#define CSMI_SAS_RAID_FEATURE_LUN_RENUMBER      0x00000010
++#define CSMI_SAS_RAID_FEATURE_SURFACE_SCAN      0x00000020
++#define CSMI_SAS_RAID_FEATURE_SPARES_SHARED     0x00000040
++
++// RAID Priority
++// (bDefaultTransformPriority, etc.)
++#define CSMI_SAS_PRIORITY_UNKNOWN   0
++#define CSMI_SAS_PRIORITY_UNCHANGED 0
++#define CSMI_SAS_PRIORITY_AUTO      1
++#define CSMI_SAS_PRIORITY_OFF       2
++#define CSMI_SAS_PRIORITY_LOW       3
++#define CSMI_SAS_PRIORITY_MEDIUM    4
++#define CSMI_SAS_PRIORITY_HIGH      5
++
++// RAID Transformation Rules
++// (uRaidSetTransformationRules)
++#define CSMI_SAS_RAID_RULE_AVAILABLE_MEMORY     0x00000001
++#define CSMI_SAS_RAID_RULE_OVERLAPPED_EXTENTS   0x00000002
++
++// RAID Cache Ratios Supported
++// (bCacheRatiosSupported)
++// from 0 to 100 defines the write to read ratio, 0 is 100% write
++#define CSMI_SAS_RAID_CACHE_RATIO_RANGE     101
++#define CSMI_SAS_RAID_CACHE_RATIO_FIXED     102
++#define CSMI_SAS_RAID_CACHE_RATIO_AUTO      103
++#define CSMI_SAS_RAID_CACHE_RATIO_END       255
++
++// RAID Cache Ratio Flag
++// (bCacheRatioFlag)
++#define CSMI_SAS_RAID_CACHE_RATIO_DISABLE   0
++#define CSMI_SAS_RAID_CACHE_RATIO_ENABLE    1
++
++// RAID Clear Configuration Signature
++// (bClearConfiguration)
++#define CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE "RAIDCLR"
++
++// RAID Failure Codes
++// (uFailCode)
++#define CSMI_SAS_FAIL_CODE_OK                           0
++#define CSMI_SAS_FAIL_CODE_PARAMETER_INVALID            1000
++#define CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID   1001
++#define CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID     1002
++#define CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID          1003
++#define CSMI_SAS_FAIL_CODE_SURFACE_SCAN_INVALID         1004
++#define CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID  1005
++#define CSMI_SAS_FAIL_CODE_ELEMENT_INDEX_INVALID        1006
++#define CSMI_SAS_FAIL_CODE_SUBELEMENT_INDEX_INVALID     1007
++#define CSMI_SAS_FAIL_CODE_EXTENT_INVALID               1008
++#define CSMI_SAS_FAIL_CODE_BLOCK_COUNT_INVALID          1009
++#define CSMI_SAS_FAIL_CODE_DRIVE_INDEX_INVALID          1010
++#define CSMI_SAS_FAIL_CODE_EXISTING_LUN_INVALID         1011
++#define CSMI_SAS_FAIL_CODE_RAID_TYPE_INVALID            1012
++#define CSMI_SAS_FAIL_CODE_STRIPE_SIZE_INVALID          1013
++#define CSMI_SAS_FAIL_CODE_TRANSFORMATION_INVALID       1014
++#define CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID         1015
++#define CSMI_SAS_FAIL_CODE_ENUMERATION_TYPE_INVALID     1016
++
++#define CSMI_SAS_FAIL_CODE_EXCEEDED_RAID_SET_COUNT      2000
++#define CSMI_SAS_FAIL_CODE_DUPLICATE_LUN                2001
++
++#define CSMI_SAS_FAIL_CODE_WAIT_FOR_OPERATION           3000
++
++// RAID Enumeration Types
++// (uEnumerationType)
++#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE                0
++#define CSMI_SAS_RAID_ELEMENT_TYPE_MODULE               1
++#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE_RAID_SET       2
++#define CSMI_SAS_RAID_ELEMENT_TYPE_EXTENT_DRIVE         3
++
++// RAID Extent Types
++// (bExtentType)
++#define CSMI_SAS_RAID_EXTENT_RESERVED       0
++#define CSMI_SAS_RAID_EXTENT_METADATA       1
++#define CSMI_SAS_RAID_EXTENT_ALLOCATED      2
++#define CSMI_SAS_RAID_EXTENT_UNALLOCATED    3
++
++// RAID Operation Types
++// (uOperationType)
++#define CSMI_SAS_RAID_SET_CREATE            0
++#define CSMI_SAS_RAID_SET_LABEL             1
++#define CSMI_SAS_RAID_SET_TRANSFORM         2
++#define CSMI_SAS_RAID_SET_DELETE            3
++#define CSMI_SAS_RAID_SET_WRITE_PROTECT     4
++#define CSMI_SAS_RAID_SET_CACHE             5
++#define CSMI_SAS_RAID_SET_ONLINE_STATE      6
++#define CSMI_SAS_RAID_SET_SPARE             7
++
++// RAID Transform Types
++// (bTransformType)
++#define CSMI_SAS_RAID_SET_TRANSFORM_SPLIT_MIRROR    0
++#define CSMI_SAS_RAID_SET_TRANSFORM_MERGE_RAID_0    1
++#define CSMI_SAS_RAID_SET_TRANSFORM_LUN_RENUMBER    2
++#define CSMI_SAS_RAID_SET_TRANSFORM_RAID_SET        3
++
++// RAID Online State
++// (bOnlineState)
++#define CSMI_SAS_RAID_SET_STATE_UNKNOWN     0
++#define CSMI_SAS_RAID_SET_STATE_ONLINE      1
++#define CSMI_SAS_RAID_SET_STATE_OFFLINE     2
++
++/* * * * * * * * * * SAS HBA Class IOCTL Constants * * * * * * * * * */
++
++// Return codes for SAS IOCTL's
++// (IoctlHeader.ReturnCode)
++
++#define CSMI_SAS_PHY_INFO_CHANGED            CSMI_SAS_STATUS_SUCCESS
++#define CSMI_SAS_PHY_INFO_NOT_CHANGEABLE     2000
++#define CSMI_SAS_LINK_RATE_OUT_OF_RANGE      2001
++
++#define CSMI_SAS_PHY_DOES_NOT_EXIST          2002
++#define CSMI_SAS_PHY_DOES_NOT_MATCH_PORT     2003
++#define CSMI_SAS_PHY_CANNOT_BE_SELECTED      2004
++#define CSMI_SAS_SELECT_PHY_OR_PORT          2005
++#define CSMI_SAS_PORT_DOES_NOT_EXIST         2006
++#define CSMI_SAS_PORT_CANNOT_BE_SELECTED     2007
++#define CSMI_SAS_CONNECTION_FAILED           2008
++
++#define CSMI_SAS_NO_SATA_DEVICE              2009
++#define CSMI_SAS_NO_SATA_SIGNATURE           2010
++#define CSMI_SAS_SCSI_EMULATION              2011
++#define CSMI_SAS_NOT_AN_END_DEVICE           2012
++#define CSMI_SAS_NO_SCSI_ADDRESS             2013
++#define CSMI_SAS_NO_DEVICE_ADDRESS           2014
++
++// Signature value
++// (IoctlHeader.Signature)
++
++#define CSMI_SAS_SIGNATURE    "CSMISAS"
++
++// Timeout value default of 60 seconds
++// (IoctlHeader.Timeout)
++
++#define CSMI_SAS_TIMEOUT      60
++
++// Device types
++// (bDeviceType)
++
++#define CSMI_SAS_PHY_UNUSED               0x00
++#define CSMI_SAS_NO_DEVICE_ATTACHED       0x00
++#define CSMI_SAS_END_DEVICE               0x10
++#define CSMI_SAS_EDGE_EXPANDER_DEVICE     0x20
++#define CSMI_SAS_FANOUT_EXPANDER_DEVICE   0x30
++
++// Protocol options
++// (bInitiatorPortProtocol, bTargetPortProtocol)
++
++#define CSMI_SAS_PROTOCOL_SATA   0x01
++#define CSMI_SAS_PROTOCOL_SMP    0x02
++#define CSMI_SAS_PROTOCOL_STP    0x04
++#define CSMI_SAS_PROTOCOL_SSP    0x08
++
++// Negotiated and hardware link rates
++// (bNegotiatedLinkRate, bMinimumLinkRate, bMaximumLinkRate)
++
++#define CSMI_SAS_LINK_RATE_UNKNOWN  0x00
++#define CSMI_SAS_PHY_DISABLED       0x01
++#define CSMI_SAS_LINK_RATE_FAILED   0x02
++#define CSMI_SAS_SATA_SPINUP_HOLD   0x03
++#define CSMI_SAS_SATA_PORT_SELECTOR 0x04
++#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08
++#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09
++#define CSMI_SAS_LINK_VIRTUAL       0x10
++
++// Discover state
++// (bAutoDiscover)
++
++#define CSMI_SAS_DISCOVER_NOT_SUPPORTED   0x00
++#define CSMI_SAS_DISCOVER_NOT_STARTED     0x01
++#define CSMI_SAS_DISCOVER_IN_PROGRESS     0x02
++#define CSMI_SAS_DISCOVER_COMPLETE        0x03
++#define CSMI_SAS_DISCOVER_ERROR           0x04
++
++// Phy features
++
++#define CSMI_SAS_PHY_VIRTUAL_SMP          0x01
++
++// Programmed link rates
++// (bMinimumLinkRate, bMaximumLinkRate)
++// (bProgrammedMinimumLinkRate, bProgrammedMaximumLinkRate)
++
++#define CSMI_SAS_PROGRAMMED_LINK_RATE_UNCHANGED 0x00
++#define CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS  0x08
++#define CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS  0x09
++
++// Link rate
++// (bNegotiatedLinkRate in CSMI_SAS_SET_PHY_INFO)
++
++#define CSMI_SAS_LINK_RATE_NEGOTIATE      0x00
++#define CSMI_SAS_LINK_RATE_PHY_DISABLED   0x01
++
++// Signal class
++// (bSignalClass in CSMI_SAS_SET_PHY_INFO)
++
++#define CSMI_SAS_SIGNAL_CLASS_UNKNOWN     0x00
++#define CSMI_SAS_SIGNAL_CLASS_DIRECT      0x01
++#define CSMI_SAS_SIGNAL_CLASS_SERVER      0x02
++#define CSMI_SAS_SIGNAL_CLASS_ENCLOSURE   0x03
++
++// Link error reset
++// (bResetCounts)
++
++#define CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS   0x00
++#define CSMI_SAS_LINK_ERROR_RESET_COUNTS        0x01
++
++// Phy identifier
++// (bPhyIdentifier)
++
++#define CSMI_SAS_USE_PORT_IDENTIFIER   0xFF
++
++// Port identifier
++// (bPortIdentifier)
++
++#define CSMI_SAS_IGNORE_PORT           0xFF
++
++// Programmed link rates
++// (bConnectionRate)
++
++#define CSMI_SAS_LINK_RATE_NEGOTIATED  0x00
++#define CSMI_SAS_LINK_RATE_1_5_GBPS    0x08
++#define CSMI_SAS_LINK_RATE_3_0_GBPS    0x09
++
++// Connection status
++// (bConnectionStatus)
++
++#define CSMI_SAS_OPEN_ACCEPT                          0
++#define CSMI_SAS_OPEN_REJECT_BAD_DESTINATION          1
++#define CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED       2
++#define CSMI_SAS_OPEN_REJECT_NO_DESTINATION           3
++#define CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED          4
++#define CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED   5
++#define CSMI_SAS_OPEN_REJECT_RESERVE_ABANDON          6
++#define CSMI_SAS_OPEN_REJECT_RESERVE_CONTINUE         7
++#define CSMI_SAS_OPEN_REJECT_RESERVE_INITIALIZE       8
++#define CSMI_SAS_OPEN_REJECT_RESERVE_STOP             9
++#define CSMI_SAS_OPEN_REJECT_RETRY                    10
++#define CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY       11
++#define CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION        12
++
++// SSP Status
++// (bSSPStatus)
++
++#define CSMI_SAS_SSP_STATUS_UNKNOWN     0x00
++#define CSMI_SAS_SSP_STATUS_WAITING     0x01
++#define CSMI_SAS_SSP_STATUS_COMPLETED   0x02
++#define CSMI_SAS_SSP_STATUS_FATAL_ERROR 0x03
++#define CSMI_SAS_SSP_STATUS_RETRY       0x04
++#define CSMI_SAS_SSP_STATUS_NO_TAG      0x05
++
++// SSP Flags
++// (uFlags)
++
++#define CSMI_SAS_SSP_READ           0x00000001
++#define CSMI_SAS_SSP_WRITE          0x00000002
++#define CSMI_SAS_SSP_UNSPECIFIED    0x00000004
++
++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_SIMPLE         0x00000000
++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE  0x00000010
++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED        0x00000020
++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA            0x00000040
++
++// SSP Data present
++// (bDataPresent)
++
++#define CSMI_SAS_SSP_NO_DATA_PRESENT         0x00
++#define CSMI_SAS_SSP_RESPONSE_DATA_PRESENT   0x01
++#define CSMI_SAS_SSP_SENSE_DATA_PRESENT      0x02
++
++// STP Flags
++// (uFlags)
++
++#define CSMI_SAS_STP_READ           0x00000001
++#define CSMI_SAS_STP_WRITE          0x00000002
++#define CSMI_SAS_STP_UNSPECIFIED    0x00000004
++#define CSMI_SAS_STP_PIO            0x00000010
++#define CSMI_SAS_STP_DMA            0x00000020
++#define CSMI_SAS_STP_PACKET         0x00000040
++#define CSMI_SAS_STP_DMA_QUEUED     0x00000080
++#define CSMI_SAS_STP_EXECUTE_DIAG   0x00000100
++#define CSMI_SAS_STP_RESET_DEVICE   0x00000200
++
++// Task Management Flags
++// (uFlags)
++
++#define CSMI_SAS_TASK_IU               0x00000001
++#define CSMI_SAS_HARD_RESET_SEQUENCE   0x00000002
++#define CSMI_SAS_SUPPRESS_RESULT       0x00000004
++
++// Task Management Functions
++// (bTaskManagement)
++
++#define CSMI_SAS_SSP_ABORT_TASK           0x01
++#define CSMI_SAS_SSP_ABORT_TASK_SET       0x02
++#define CSMI_SAS_SSP_CLEAR_TASK_SET       0x04
++#define CSMI_SAS_SSP_LOGICAL_UNIT_RESET   0x08
++#define CSMI_SAS_SSP_CLEAR_ACA            0x40
++#define CSMI_SAS_SSP_QUERY_TASK           0x80
++
++// Task Management Information
++// (uInformation)
++
++#define CSMI_SAS_SSP_TEST           1
++#define CSMI_SAS_SSP_EXCEEDED       2
++#define CSMI_SAS_SSP_DEMAND         3
++#define CSMI_SAS_SSP_TRIGGER        4
++
++// Connector Pinout Information
++// (uPinout)
++
++#define CSMI_SAS_CON_UNKNOWN              0x00000001
++#define CSMI_SAS_CON_SFF_8482             0x00000002
++#define CSMI_SAS_CON_SFF_8470_LANE_1      0x00000100
++#define CSMI_SAS_CON_SFF_8470_LANE_2      0x00000200
++#define CSMI_SAS_CON_SFF_8470_LANE_3      0x00000400
++#define CSMI_SAS_CON_SFF_8470_LANE_4      0x00000800
++#define CSMI_SAS_CON_SFF_8484_LANE_1      0x00010000
++#define CSMI_SAS_CON_SFF_8484_LANE_2      0x00020000
++#define CSMI_SAS_CON_SFF_8484_LANE_3      0x00040000
++#define CSMI_SAS_CON_SFF_8484_LANE_4      0x00080000
++
++// Connector Location Information
++// (bLocation)
++
++// same as uPinout above...
++// #define CSMI_SAS_CON_UNKNOWN              0x01
++#define CSMI_SAS_CON_INTERNAL             0x02
++#define CSMI_SAS_CON_EXTERNAL             0x04
++#define CSMI_SAS_CON_SWITCHABLE           0x08
++#define CSMI_SAS_CON_AUTO                 0x10
++#define CSMI_SAS_CON_NOT_PRESENT          0x20
++#define CSMI_SAS_CON_NOT_CONNECTED        0x80
++
++// Device location identification
++// (bIdentify)
++
++#define CSMI_SAS_LOCATE_UNKNOWN           0x00
++#define CSMI_SAS_LOCATE_FORCE_OFF         0x01
++#define CSMI_SAS_LOCATE_FORCE_ON          0x02
++
++// Location Valid flags
++// (uLocationFlags)
++
++#define CSMI_SAS_LOCATE_SAS_ADDRESS_VALID           0x00000001
++#define CSMI_SAS_LOCATE_SAS_LUN_VALID               0x00000002
++#define CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID  0x00000004
++#define CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID        0x00000008
++#define CSMI_SAS_LOCATE_BAY_PREFIX_VALID            0x00000010
++#define CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID        0x00000020
++#define CSMI_SAS_LOCATE_LOCATION_STATE_VALID        0x00000040
++
++/* * * * * * * * SAS Phy Control Class IOCTL Constants * * * * * * * * */
++
++// Return codes for SAS Phy Control IOCTL's
++// (IoctlHeader.ReturnCode)
++
++// Signature value
++// (IoctlHeader.Signature)
++
++#define CSMI_PHY_SIGNATURE    "CSMIPHY"
++
++// Phy Control Functions
++// (bFunction)
++
++// values 0x00 to 0xFF are consistent in definition with the SMP PHY CONTROL 
++// function defined in the SAS spec
++#define CSMI_SAS_PC_NOP                   0x00000000
++#define CSMI_SAS_PC_LINK_RESET            0x00000001
++#define CSMI_SAS_PC_HARD_RESET            0x00000002
++#define CSMI_SAS_PC_PHY_DISABLE           0x00000003
++// 0x04 to 0xFF reserved...
++#define CSMI_SAS_PC_GET_PHY_SETTINGS      0x00000100
++
++// Link Flags
++#define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
++#define CSMI_SAS_PHY_UPDATE_SPINUP_RATE   0x00000002
++#define CSMI_SAS_PHY_AUTO_COMWAKE         0x00000004
++
++// Device Types for Phy Settings
++// (bType)
++#define CSMI_SAS_UNDEFINED 0x00
++#define CSMI_SAS_SATA      0x01
++#define CSMI_SAS_SAS       0x02
++
++// Transmitter Flags
++// (uTransmitterFlags)
++#define CSMI_SAS_PHY_PREEMPHASIS_DISABLED    0x00000001
++
++// Receiver Flags
++// (uReceiverFlags)
++#define CSMI_SAS_PHY_EQUALIZATION_DISABLED   0x00000001
++
++// Pattern Flags
++// (uPatternFlags)
++// #define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001
++#define CSMI_SAS_PHY_DISABLE_SCRAMBLING      0x00000002
++#define CSMI_SAS_PHY_DISABLE_ALIGN           0x00000004
++#define CSMI_SAS_PHY_DISABLE_SSC             0x00000008
++
++#define CSMI_SAS_PHY_FIXED_PATTERN           0x00000010
++#define CSMI_SAS_PHY_USER_PATTERN            0x00000020
++
++// Fixed Patterns
++// (bFixedPattern)
++#define CSMI_SAS_PHY_CJPAT                   0x00000001
++#define CSMI_SAS_PHY_ALIGN                   0x00000002
++
++// Type Flags
++// (bTypeFlags)
++#define CSMI_SAS_PHY_POSITIVE_DISPARITY      0x01
++#define CSMI_SAS_PHY_NEGATIVE_DISPARITY      0x02
++#define CSMI_SAS_PHY_CONTROL_CHARACTER       0x04
++
++// Miscellaneous
++#define SLOT_NUMBER_UNKNOWN   0xFFFF
++
++/*************************************************************************/
++/* DATA STRUCTURES                                                       */
++/*************************************************************************/
++
++/* * * * * * * * * * Class Independent Structures * * * * * * * * * */
++
++// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
++#pragma pack(8)
++
++// CC_CSMI_SAS_DRIVER_INFO
++
++typedef struct _CSMI_SAS_DRIVER_INFO {
++   __u8  szName[81];
++   __u8  szDescription[81];
++   __u16 usMajorRevision;
++   __u16 usMinorRevision;
++   __u16 usBuildRevision;
++   __u16 usReleaseRevision;
++   __u16 usCSMIMajorRevision;
++   __u16 usCSMIMinorRevision;
++} CSMI_SAS_DRIVER_INFO,
++  *PCSMI_SAS_DRIVER_INFO;
++
++typedef struct _CSMI_SAS_DRIVER_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_DRIVER_INFO Information;
++} CSMI_SAS_DRIVER_INFO_BUFFER,
++  *PCSMI_SAS_DRIVER_INFO_BUFFER;
++
++// CC_CSMI_SAS_CNTLR_CONFIGURATION
++
++typedef struct _CSMI_SAS_PCI_BUS_ADDRESS {
++   __u8  bBusNumber;
++   __u8  bDeviceNumber;
++   __u8  bFunctionNumber;
++   __u8  bReserved;
++} CSMI_SAS_PCI_BUS_ADDRESS,
++  *PCSMI_SAS_PCI_BUS_ADDRESS;
++
++typedef union _CSMI_SAS_IO_BUS_ADDRESS {
++   CSMI_SAS_PCI_BUS_ADDRESS PciAddress;
++   __u8  bReserved[32];
++} CSMI_SAS_IO_BUS_ADDRESS,
++  *PCSMI_SAS_IO_BUS_ADDRESS;
++
++typedef struct _CSMI_SAS_CNTLR_CONFIG {
++   __u32 uBaseIoAddress;
++   struct {
++      __u32 uLowPart;
++      __u32 uHighPart;
++   } BaseMemoryAddress;
++   __u32 uBoardID;
++   __u16 usSlotNumber;
++   __u8  bControllerClass;
++   __u8  bIoBusType;
++   CSMI_SAS_IO_BUS_ADDRESS BusAddress;
++   __u8  szSerialNumber[81];
++   __u16 usMajorRevision;
++   __u16 usMinorRevision;
++   __u16 usBuildRevision;
++   __u16 usReleaseRevision;
++   __u16 usBIOSMajorRevision;
++   __u16 usBIOSMinorRevision;
++   __u16 usBIOSBuildRevision;
++   __u16 usBIOSReleaseRevision;
++   __u32 uControllerFlags;
++   __u16 usRromMajorRevision;
++   __u16 usRromMinorRevision;
++   __u16 usRromBuildRevision;
++   __u16 usRromReleaseRevision;
++   __u16 usRromBIOSMajorRevision;
++   __u16 usRromBIOSMinorRevision;
++   __u16 usRromBIOSBuildRevision;
++   __u16 usRromBIOSReleaseRevision;
++   __u8  bReserved[7];
++} CSMI_SAS_CNTLR_CONFIG,
++  *PCSMI_SAS_CNTLR_CONFIG;
++
++typedef struct _CSMI_SAS_CNTLR_CONFIG_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_CNTLR_CONFIG Configuration;
++} CSMI_SAS_CNTLR_CONFIG_BUFFER,
++  *PCSMI_SAS_CNTLR_CONFIG_BUFFER;
++
++// CC_CSMI_SAS_CNTLR_STATUS
++
++typedef struct _CSMI_SAS_CNTLR_STATUS {
++   __u32 uStatus;
++   __u32 uOfflineReason;
++   __u8  bReserved[28];
++} CSMI_SAS_CNTLR_STATUS,
++  *PCSMI_SAS_CNTLR_STATUS;
++
++typedef struct _CSMI_SAS_CNTLR_STATUS_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_CNTLR_STATUS Status;
++} CSMI_SAS_CNTLR_STATUS_BUFFER,
++  *PCSMI_SAS_CNTLR_STATUS_BUFFER;
++
++// CC_CSMI_SAS_FIRMWARE_DOWNLOAD
++
++typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD {
++   __u32 uBufferLength;
++   __u32 uDownloadFlags;
++   __u8  bReserved[32];
++   __u16 usStatus;
++   __u16 usSeverity;
++} CSMI_SAS_FIRMWARE_DOWNLOAD,
++  *PCSMI_SAS_FIRMWARE_DOWNLOAD;
++
++typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_FIRMWARE_DOWNLOAD Information;
++   __u8  bDataBuffer[1];
++} CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER,
++  *PCSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER;
++
++// CC_CSMI_SAS_RAID_INFO
++
++typedef struct _CSMI_SAS_RAID_INFO {
++   __u32 uNumRaidSets;
++   __u32 uMaxDrivesPerSet;
++   __u32 uMaxRaidSets;
++   __u8  bMaxRaidTypes;
++   __u8  bReservedByteFields[7];
++   __u64 ulMinRaidSetBlocks;
++   __u64 ulMaxRaidSetBlocks;
++   __u32 uMaxPhysicalDrives;
++   __u32 uMaxExtents;
++   __u32 uMaxModules;
++   __u32 uMaxTransformationMemory;
++   __u32 uChangeCount;
++   __u8  bReserved[44];
++} CSMI_SAS_RAID_INFO,
++  *PCSMI_SAS_RAID_INFO;
++
++typedef struct _CSMI_SAS_RAID_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_INFO Information;
++} CSMI_SAS_RAID_INFO_BUFFER,
++  *PCSMI_SAS_RAID_INFO_BUFFER;
++
++// CC_CSMI_SAS_GET_RAID_CONFIG
++
++typedef struct _CSMI_SAS_RAID_DRIVES {
++   __u8  bModel[40];
++   __u8  bFirmware[8];
++   __u8  bSerialNumber[40];
++   __u8  bSASAddress[8];
++   __u8  bSASLun[8];
++   __u8  bDriveStatus;
++   __u8  bDriveUsage;
++   __u8  bDriveType;
++   __u16 usBlockSize;
++   __u8  bReserved[15];
++   __u32 uDriveIndex;
++   __u64 ulTotalUserBlocks;
++} CSMI_SAS_RAID_DRIVES,
++  *PCSMI_SAS_RAID_DRIVES;
++
++typedef struct _CSMI_SAS_RAID_DEVICE_ID {
++   __u8  bDeviceIdentificationVPDPage[1];
++} CSMI_SAS_RAID_DEVICE_ID,
++  *PCSMI_SAS_RAID_DEVICE_ID;
++
++typedef struct _CSMI_SAS_RAID_SET_ADDITIONAL_DATA {
++   __u8  bLabel[16];
++   __u8  bRaidSetLun[8];
++   __u8  bWriteProtection;
++   __u8  bCacheSetting;
++   __u8  bCacheRatio;
++   __u16 usBlockSize;
++   __u8  bReservedBytes[11];
++   __u64 ulRaidSetExtentOffset;
++   __u64 ulRaidSetBlocks;
++   __u32 uStripeSizeInBlocks;
++   __u32 uSectorsPerTrack;
++   __u8  bApplicationScratchPad[16];
++   __u32 uNumberOfHeads;
++   __u32 uNumberOfTracks;
++   __u8  bReserved[24];
++} CSMI_SAS_RAID_SET_ADDITIONAL_DATA,
++  *PCSMI_SAS_RAID_SET_ADDITIONAL_DATA;
++
++typedef struct _CSMI_SAS_RAID_CONFIG {
++   __u32 uRaidSetIndex;
++   __u32 uCapacity;
++   __u32 uStripeSize;
++   __u8  bRaidType;
++   __u8  bStatus;
++   __u8  bInformation;
++   __u8  bDriveCount;
++   __u8  bDataType;
++   __u8  bReserved[15];
++   __u32 uChangeCount;
++   union {
++      CSMI_SAS_RAID_DRIVES Drives[1];
++      CSMI_SAS_RAID_DEVICE_ID DeviceId[1];
++      CSMI_SAS_RAID_SET_ADDITIONAL_DATA Data[1];
++   };
++} CSMI_SAS_RAID_CONFIG,
++   *PCSMI_SAS_RAID_CONFIG;
++
++typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_CONFIG Configuration;
++} CSMI_SAS_RAID_CONFIG_BUFFER,
++  *PCSMI_SAS_RAID_CONFIG_BUFFER;
++
++// CC_CSMI_SAS_GET_RAID_FEATURES
++
++typedef struct _CSMI_SAS_RAID_TYPE_DESCRIPTION {
++  __u8  bRaidType;
++  __u8  bReservedBytes[7];
++  __u32 uSupportedStripeSizeMap;
++  __u8  bReserved[24];
++} CSMI_SAS_RAID_TYPE_DESCRIPTION, 
++  *PCSMI_SAS_RAID_TYPE_DESCRIPTION;
++
++typedef struct _CSMI_SAS_RAID_FEATURES {
++   __u32 uFeatures;
++   __u8  bReservedFeatures[32];
++   __u8  bDefaultTransformPriority;
++   __u8  bTransformPriority;
++   __u8  bDefaultRebuildPriority;
++   __u8  bRebuildPriority;
++   __u8  bDefaultSurfaceScanPriority;
++   __u8  bSurfaceScanPriority;
++   __u16 usReserved;
++   __u32 uRaidSetTransformationRules;
++   __u32 uReserved[11];
++   CSMI_SAS_RAID_TYPE_DESCRIPTION RaidType[24];
++   __u8  bCacheRatiosSupported[104];
++   __u32 uChangeCount;
++   __u8  bReserved[124];
++} CSMI_SAS_RAID_FEATURES,
++  *PCSMI_SAS_RAID_FEATURES;
++
++typedef struct _CSMI_SAS_RAID_FEATURES_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_FEATURES Information;
++} CSMI_SAS_RAID_FEATURES_BUFFER,
++  *PCSMI_SAS_RAID_FEATURES_BUFFER;
++
++// CC_CSMI_SAS_SET_RAID_CONTROL
++
++typedef struct _CSMI_SAS_RAID_CONTROL {
++   __u8  bTransformPriority;
++   __u8  bRebuildPriority;
++   __u8  bCacheRatioFlag;
++   __u8  bCacheRatio;
++   __u8  bSurfaceScanPriority;
++   __u8  bReservedBytes[15];
++   __u8  bClearConfiguration[8];
++   __u32 uChangeCount;
++   __u8  bReserved[88];
++   __u32 uFailureCode;
++   __u8  bFailureDescription[80];
++} CSMI_SAS_RAID_CONTROL,
++  *PCSMI_SAS_RAID_CONTROL;
++
++typedef struct _CSMI_SAS_RAID_CONTROL_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_CONTROL Information;
++} CSMI_SAS_RAID_CONTROL_BUFFER,
++  *PCSMI_SAS_RAID_CONTROL_BUFFER;
++
++// CC_CSMI_SAS_GET_RAID_ELEMENT
++
++typedef struct _CSMI_SAS_DRIVE_EXTENT_INFO {
++   __u32 uDriveIndex;
++   __u8  bExtentType;
++   __u8  bReservedBytes[7];
++   __u64 ulExtentOffset;
++   __u64 ulExtentBlocks;
++   __u32 uRaidSetIndex;
++   __u8  bReserved[96];
++} CSMI_SAS_DRIVE_EXTENT_INFO, 
++  *PCSMI_SAS_DRIVE_EXTENT_INFO;
++
++typedef struct _CSMI_SAS_RAID_MODULE_INFO {
++   __u8  bReserved[128];
++} CSMI_SAS_RAID_MODULE_INFO, 
++  *PCSMI_SAS_RAID_MODULE_INFO;
++
++typedef struct _CSMI_SAS_DRIVE_LOCATION {
++   __u8  bConnector[16];
++   __u8  bBoxName[16];
++   __u32 uBay;
++   __u8  bReservedBytes[4];
++   __u8  bAttachedSASAddress[8];
++   __u8  bAttachedPhyIdentifier;
++   __u8  bReserved[79];
++} CSMI_SAS_DRIVE_LOCATION, 
++  *PCSMI_SAS_DRIVE_LOCATION;
++
++typedef struct _CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA {
++   __u8  bNegotiatedLinkRate[2];
++   __u8  bReserved[126];
++} CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA, 
++  *PCSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA;
++
++typedef struct _CSMI_SAS_DRIVE_INFO {
++   CSMI_SAS_RAID_DRIVES Device;
++   CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA Data;
++   CSMI_SAS_DRIVE_LOCATION Location; 
++   __u8  bReserved[16];
++} CSMI_SAS_DRIVE_INFO, 
++  *PCSMI_SAS_DRIVE_INFO;
++
++typedef struct _CSMI_SAS_RAID_ELEMENT { 
++   __u32 uEnumerationType;
++   __u32 uElementIndex;
++   __u32 uNumElements;
++   __u32 uChangeCount;
++   __u32 uSubElementIndex;
++   __u8  bReserved[32];
++   __u32 uFailureCode;
++   __u8  bFailureDescription[80];
++   union {
++       CSMI_SAS_DRIVE_INFO Drive;
++       CSMI_SAS_RAID_MODULE_INFO Module;
++       CSMI_SAS_DRIVE_EXTENT_INFO Extent;
++   } Element;
++} CSMI_SAS_RAID_ELEMENT,
++  *PCSMI_SAS_RAID_ELEMENT;
++
++typedef struct _CSMI_SAS_RAID_ELEMENT_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_ELEMENT Information;
++} CSMI_SAS_RAID_ELEMENT_BUFFER,
++  *PCSMI_SAS_RAID_ELEMENT_BUFFER;
++
++// CC_CSMI_SAS_SET_RAID_OPERATION
++
++typedef struct _CSMI_SAS_RAID_SET_LIST {
++   __u32 uRaidSetIndex;
++   __u8  bExistingLun[8]; 
++   __u8  bNewLun[8]; 
++   __u8  bReserved[12];
++} CSMI_SAS_RAID_SET_LIST, 
++  *PCSMI_SAS_RAID_SET_LIST;
++
++typedef struct _CSMI_SAS_RAID_SET_DRIVE_LIST {
++   __u32 uDriveIndex;
++   __u8  bDriveUsage;
++   __u8  bReserved[27];
++} CSMI_SAS_RAID_SET_DRIVE_LIST, 
++  *PCSMI_SAS_RAID_SET_DRIVE_LIST;
++
++typedef struct _CSMI_SAS_RAID_SET_SPARE_INFO {
++   __u32 uRaidSetIndex;
++   __u32 uDriveCount;
++   __u8  bApplicationScratchPad[16];
++   __u8  bReserved[104];  
++} CSMI_SAS_RAID_SET_SPARE_INFO, 
++  *PCSMI_SAS_RAID_SET_SPARE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_ONLINE_STATE_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bOnlineState;
++   __u8  bReserved[123];  
++} CSMI_SAS_RAID_SET_ONLINE_STATE_INFO, 
++  *PCSMI_SAS_RAID_SET_ONLINE_STATE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_CACHE_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bCacheSetting;
++   __u8  bCacheRatioFlag;
++   __u8  bCacheRatio;
++   __u8  bReserved[121];  
++} CSMI_SAS_RAID_SET_CACHE_INFO, 
++  *PCSMI_SAS_RAID_SET_CACHE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bWriteProtectSetting;
++   __u8  bReserved[123];  
++} CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO, 
++  *PCSMI_SAS_RAID_SET_WRITE_PROTECT_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_DELETE_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bReserved[124];  
++} CSMI_SAS_RAID_SET_DELETE_INFO, 
++  *PCSMI_SAS_RAID_SET_DELETE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_MODIFY_INFO {
++   __u8  bRaidType;
++   __u8  bReservedBytes[7];
++   __u32 uStripeSize;
++   __u64 ulRaidSetBlocks;
++   __u64 ulRaidSetExtentOffset;
++   __u32 uDriveCount;
++   __u8  bReserved[96];
++} CSMI_SAS_RAID_SET_MODIFY_INFO, 
++  *PCSMI_SAS_RAID_SET_MODIFY_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_TRANSFORM_INFO {
++   __u8  bTransformType;
++   __u8  bReservedBytes[3];
++   __u32 uRaidSetIndex;
++   __u8  bRaidType;
++   __u8  bReservedBytes2[11];
++   __u32 uAdditionalRaidSetIndex;
++   __u32 uRaidSetCount;
++   __u8  bApplicationScratchPad[16];
++   CSMI_SAS_RAID_SET_MODIFY_INFO Modify;
++   __u8  bReserved[80];
++} CSMI_SAS_RAID_SET_TRANSFORM_INFO, 
++  *PCSMI_SAS_RAID_SET_TRANSFORM_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_LABEL_INFO {
++   __u32 uRaidSetIndex;
++   __u8  bLabel[16];
++   __u8  bReserved[108];  
++} CSMI_SAS_RAID_SET_LABEL_INFO, 
++  *PCSMI_SAS_RAID_SET_LABEL_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_CREATE_INFO {
++   __u8  bRaidType;
++   __u8  bReservedBytes[7];
++   __u32 uStripeSize;
++   __u32 uTrackSectorCount;
++   __u64 ulRaidSetBlocks; 
++   __u64 ulRaidSetExtentOffset;
++   __u32 uDriveCount;
++   __u8  bLabel[16];
++   __u32 uRaidSetIndex;
++   __u8  bApplicationScratchPad[16];
++   __u32 uNumberOfHeads;
++   __u32 uNumberOfTracks;
++   __u8  bReserved[48];  
++} CSMI_SAS_RAID_SET_CREATE_INFO, 
++  *PCSMI_SAS_RAID_SET_CREATE_INFO;
++
++typedef struct _CSMI_SAS_RAID_SET_OPERATION { 
++   __u32 uOperationType;
++   __u32 uChangeCount;
++   __u32 uFailureCode;
++   __u8  bFailureDescription[80];
++   __u8  bReserved[28];
++   union {
++       CSMI_SAS_RAID_SET_CREATE_INFO Create;
++       CSMI_SAS_RAID_SET_LABEL_INFO Label;
++       CSMI_SAS_RAID_SET_TRANSFORM_INFO Transform;
++       CSMI_SAS_RAID_SET_DELETE_INFO Delete;
++       CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO Protect;
++       CSMI_SAS_RAID_SET_CACHE_INFO Cache;
++       CSMI_SAS_RAID_SET_ONLINE_STATE_INFO State;
++       CSMI_SAS_RAID_SET_SPARE_INFO Spare;
++   } Operation;
++   union {
++       CSMI_SAS_RAID_SET_DRIVE_LIST DriveList[1];
++       CSMI_SAS_RAID_SET_LIST RaidSetList[1];
++   } Parameters;
++} CSMI_SAS_RAID_SET_OPERATION,
++  *PCSMI_SAS_RAID_SET_OPERATION;
++
++typedef struct _CSMI_SAS_RAID_SET_OPERATION_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_RAID_SET_OPERATION Information;
++} CSMI_SAS_RAID_SET_OPERATION_BUFFER,
++  *PCSMI_SAS_RAID_SET_OPERATION_BUFFER;
++
++/* * * * * * * * * * SAS HBA Class Structures * * * * * * * * * */
++
++// CC_CSMI_SAS_GET_PHY_INFO
++
++typedef struct _CSMI_SAS_IDENTIFY {
++   __u8  bDeviceType;
++   __u8  bRestricted;
++   __u8  bInitiatorPortProtocol;
++   __u8  bTargetPortProtocol;
++   __u8  bRestricted2[8];
++   __u8  bSASAddress[8];
++   __u8  bPhyIdentifier;
++   __u8  bSignalClass;
++   __u8  bReserved[6];
++} CSMI_SAS_IDENTIFY,
++  *PCSMI_SAS_IDENTIFY;
++
++typedef struct _CSMI_SAS_PHY_ENTITY {
++   CSMI_SAS_IDENTIFY Identify;
++   __u8  bPortIdentifier;
++   __u8  bNegotiatedLinkRate;
++   __u8  bMinimumLinkRate;
++   __u8  bMaximumLinkRate;
++   __u8  bPhyChangeCount;
++   __u8  bAutoDiscover;
++   __u8  bPhyFeatures;
++   __u8  bReserved;
++   CSMI_SAS_IDENTIFY Attached;
++} CSMI_SAS_PHY_ENTITY,
++  *PCSMI_SAS_PHY_ENTITY;
++
++typedef struct _CSMI_SAS_PHY_INFO {
++   __u8  bNumberOfPhys;
++   __u8  bReserved[3];
++   CSMI_SAS_PHY_ENTITY Phy[32];
++} CSMI_SAS_PHY_INFO,
++  *PCSMI_SAS_PHY_INFO;
++
++typedef struct _CSMI_SAS_PHY_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_PHY_INFO Information;
++} CSMI_SAS_PHY_INFO_BUFFER,
++  *PCSMI_SAS_PHY_INFO_BUFFER;
++
++// CC_CSMI_SAS_SET_PHY_INFO
++
++typedef struct _CSMI_SAS_SET_PHY_INFO {
++   __u8  bPhyIdentifier;
++   __u8  bNegotiatedLinkRate;
++   __u8  bProgrammedMinimumLinkRate;
++   __u8  bProgrammedMaximumLinkRate;
++   __u8  bSignalClass;
++   __u8  bReserved[3];
++} CSMI_SAS_SET_PHY_INFO,
++  *PCSMI_SAS_SET_PHY_INFO;
++
++typedef struct _CSMI_SAS_SET_PHY_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SET_PHY_INFO Information;
++} CSMI_SAS_SET_PHY_INFO_BUFFER,
++  *PCSMI_SAS_SET_PHY_INFO_BUFFER;
++
++// CC_CSMI_SAS_GET_LINK_ERRORS
++
++typedef struct _CSMI_SAS_LINK_ERRORS {
++   __u8  bPhyIdentifier;
++   __u8  bResetCounts;
++   __u8  bReserved[2];
++   __u32 uInvalidDwordCount;
++   __u32 uRunningDisparityErrorCount;
++   __u32 uLossOfDwordSyncCount;
++   __u32 uPhyResetProblemCount;
++} CSMI_SAS_LINK_ERRORS,
++  *PCSMI_SAS_LINK_ERRORS;
++
++typedef struct _CSMI_SAS_LINK_ERRORS_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_LINK_ERRORS Information;
++} CSMI_SAS_LINK_ERRORS_BUFFER,
++  *PCSMI_SAS_LINK_ERRORS_BUFFER;
++
++// CC_CSMI_SAS_SMP_PASSTHRU
++
++typedef struct _CSMI_SAS_SMP_REQUEST {
++   __u8  bFrameType;
++   __u8  bFunction;
++   __u8  bReserved[2];
++   __u8  bAdditionalRequestBytes[1016];
++} CSMI_SAS_SMP_REQUEST,
++  *PCSMI_SAS_SMP_REQUEST;
++
++typedef struct _CSMI_SAS_SMP_RESPONSE {
++   __u8  bFrameType;
++   __u8  bFunction;
++   __u8  bFunctionResult;
++   __u8  bReserved;
++   __u8  bAdditionalResponseBytes[1016];
++} CSMI_SAS_SMP_RESPONSE,
++  *PCSMI_SAS_SMP_RESPONSE;
++
++typedef struct _CSMI_SAS_SMP_PASSTHRU {
++   __u8  bPhyIdentifier;
++   __u8  bPortIdentifier;
++   __u8  bConnectionRate;
++   __u8  bReserved;
++   __u8  bDestinationSASAddress[8];
++   __u32 uRequestLength;
++   CSMI_SAS_SMP_REQUEST Request;
++   __u8  bConnectionStatus;
++   __u8  bReserved2[3];
++   __u32 uResponseBytes;
++   CSMI_SAS_SMP_RESPONSE Response;
++} CSMI_SAS_SMP_PASSTHRU,
++  *PCSMI_SAS_SMP_PASSTHRU;
++
++typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SMP_PASSTHRU Parameters;
++} CSMI_SAS_SMP_PASSTHRU_BUFFER,
++  *PCSMI_SAS_SMP_PASSTHRU_BUFFER;
++
++// CC_CSMI_SAS_SSP_PASSTHRU
++
++typedef struct _CSMI_SAS_SSP_PASSTHRU {
++   __u8  bPhyIdentifier;
++   __u8  bPortIdentifier;
++   __u8  bConnectionRate;
++   __u8  bReserved;
++   __u8  bDestinationSASAddress[8];
++   __u8  bLun[8];
++   __u8  bCDBLength;
++   __u8  bAdditionalCDBLength;
++   __u8  bReserved2[2];
++   __u8  bCDB[16];
++   __u32 uFlags;
++   __u8  bAdditionalCDB[24];
++   __u32 uDataLength;
++} CSMI_SAS_SSP_PASSTHRU,
++  *PCSMI_SAS_SSP_PASSTHRU;
++
++typedef struct _CSMI_SAS_SSP_PASSTHRU_STATUS {
++   __u8  bConnectionStatus;
++   __u8  bSSPStatus;
++   __u8  bReserved[2];
++   __u8  bDataPresent;
++   __u8  bStatus;
++   __u8  bResponseLength[2];
++   __u8  bResponse[256];
++   __u32 uDataBytes;
++} CSMI_SAS_SSP_PASSTHRU_STATUS,
++  *PCSMI_SAS_SSP_PASSTHRU_STATUS;
++
++typedef struct _CSMI_SAS_SSP_PASSTHRU_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SSP_PASSTHRU Parameters;
++   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
++   __u8  bDataBuffer[1];
++} CSMI_SAS_SSP_PASSTHRU_BUFFER,
++  *PCSMI_SAS_SSP_PASSTHRU_BUFFER;
++
++// CC_CSMI_SAS_STP_PASSTHRU
++
++typedef struct _CSMI_SAS_STP_PASSTHRU {
++   __u8  bPhyIdentifier;
++   __u8  bPortIdentifier;
++   __u8  bConnectionRate;
++   __u8  bReserved;
++   __u8  bDestinationSASAddress[8];
++   __u8  bReserved2[4];
++   __u8  bCommandFIS[20];
++   __u32 uFlags;
++   __u32 uDataLength;
++} CSMI_SAS_STP_PASSTHRU,
++  *PCSMI_SAS_STP_PASSTHRU;
++
++typedef struct _CSMI_SAS_STP_PASSTHRU_STATUS {
++   __u8  bConnectionStatus;
++   __u8  bReserved[3];
++   __u8  bStatusFIS[20];
++   __u32 uSCR[16];
++   __u32 uDataBytes;
++} CSMI_SAS_STP_PASSTHRU_STATUS,
++  *PCSMI_SAS_STP_PASSTHRU_STATUS;
++
++typedef struct _CSMI_SAS_STP_PASSTHRU_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_STP_PASSTHRU Parameters;
++   CSMI_SAS_STP_PASSTHRU_STATUS Status;
++   __u8  bDataBuffer[1];
++} CSMI_SAS_STP_PASSTHRU_BUFFER,
++  *PCSMI_SAS_STP_PASSTHRU_BUFFER;
++
++// CC_CSMI_SAS_GET_SATA_SIGNATURE
++
++typedef struct _CSMI_SAS_SATA_SIGNATURE {
++   __u8  bPhyIdentifier;
++   __u8  bReserved[3];
++   __u8  bSignatureFIS[20];
++} CSMI_SAS_SATA_SIGNATURE,
++  *PCSMI_SAS_SATA_SIGNATURE;
++
++typedef struct _CSMI_SAS_SATA_SIGNATURE_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SATA_SIGNATURE Signature;
++} CSMI_SAS_SATA_SIGNATURE_BUFFER,
++  *PCSMI_SAS_SATA_SIGNATURE_BUFFER;
++
++// CC_CSMI_SAS_GET_SCSI_ADDRESS
++
++typedef struct _CSMI_SAS_GET_SCSI_ADDRESS_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   __u8  bSASAddress[8];
++   __u8  bSASLun[8];
++   __u8  bHostIndex;
++   __u8  bPathId;
++   __u8  bTargetId;
++   __u8  bLun;
++} CSMI_SAS_GET_SCSI_ADDRESS_BUFFER,
++   *PCSMI_SAS_GET_SCSI_ADDRESS_BUFFER;
++
++// CC_CSMI_SAS_GET_DEVICE_ADDRESS
++
++typedef struct _CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   __u8  bHostIndex;
++   __u8  bPathId;
++   __u8  bTargetId;
++   __u8  bLun;
++   __u8  bSASAddress[8];
++   __u8  bSASLun[8];
++} CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER,
++  *PCSMI_SAS_GET_DEVICE_ADDRESS_BUFFER;
++
++// CC_CSMI_SAS_TASK_MANAGEMENT
++
++typedef struct _CSMI_SAS_SSP_TASK_IU {
++   __u8  bHostIndex;
++   __u8  bPathId;
++   __u8  bTargetId;
++   __u8  bLun;
++   __u32 uFlags;
++   __u32 uQueueTag;
++   __u32 uReserved;
++   __u8  bTaskManagementFunction;
++   __u8  bReserved[7];
++   __u32 uInformation;
++} CSMI_SAS_SSP_TASK_IU,
++  *PCSMI_SAS_SSP_TASK_IU;
++
++typedef struct _CSMI_SAS_SSP_TASK_IU_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_SSP_TASK_IU Parameters;
++   CSMI_SAS_SSP_PASSTHRU_STATUS Status;
++} CSMI_SAS_SSP_TASK_IU_BUFFER,
++  *PCSMI_SAS_SSP_TASK_IU_BUFFER;
++
++// CC_CSMI_SAS_GET_CONNECTOR_INFO
++
++typedef struct _CSMI_SAS_GET_CONNECTOR_INFO {
++   __u32 uPinout;
++   __u8  bConnector[16];
++   __u8  bLocation;
++   __u8  bReserved[15];
++} CSMI_SAS_CONNECTOR_INFO,
++  *PCSMI_SAS_CONNECTOR_INFO;
++
++typedef struct _CSMI_SAS_CONNECTOR_INFO_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   CSMI_SAS_CONNECTOR_INFO Reference[32];
++} CSMI_SAS_CONNECTOR_INFO_BUFFER,
++  *PCSMI_SAS_CONNECTOR_INFO_BUFFER;
++
++// CC_CSMI_SAS_GET_LOCATION
++
++typedef struct _CSMI_SAS_LOCATION_IDENTIFIER {
++   __u32 bLocationFlags;
++   __u8  bSASAddress[8];
++   __u8  bSASLun[8];
++   __u8  bEnclosureIdentifier[8];
++   __u8  bEnclosureName[32];
++   __u8  bBayPrefix[32];
++   __u8  bBayIdentifier;
++   __u8  bLocationState;
++   __u8  bReserved[2];
++} CSMI_SAS_LOCATION_IDENTIFIER,
++  *PCSMI_SAS_LOCATION_IDENTIFIER;
++
++typedef struct _CSMI_SAS_GET_LOCATION_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   __u8  bHostIndex;
++   __u8  bPathId;
++   __u8  bTargetId;
++   __u8  bLun;
++   __u8  bIdentify;
++   __u8  bNumberOfLocationIdentifiers;
++   __u8  bLengthOfLocationIdentifier;
++   CSMI_SAS_LOCATION_IDENTIFIER Location[1];
++} CSMI_SAS_GET_LOCATION_BUFFER,
++  *PCSMI_SAS_GET_LOCATION_BUFFER;
++
++// CC_CSMI_SAS_PHY_CONTROL
++
++typedef struct _CSMI_SAS_CHARACTER {
++   __u8  bTypeFlags;
++   __u8  bValue;
++} CSMI_SAS_CHARACTER,
++  *PCSMI_SAS_CHARACTER;
++
++typedef struct _CSMI_SAS_PHY_CONTROL {
++   __u8  bType;
++   __u8  bRate;
++   __u8  bReserved[6];
++   __u32 uVendorUnique[8];
++   __u32 uTransmitterFlags;
++   __i8  bTransmitAmplitude;
++   __i8  bTransmitterPreemphasis;
++   __i8  bTransmitterSlewRate;
++   __i8  bTransmitterReserved[13];
++   __u8  bTransmitterVendorUnique[64];
++   __u32 uReceiverFlags;
++   __i8  bReceiverThreshold;
++   __i8  bReceiverEqualizationGain;
++   __i8  bReceiverReserved[14];
++   __u8  bReceiverVendorUnique[64];
++   __u32 uPatternFlags;
++   __u8  bFixedPattern;
++   __u8  bUserPatternLength;
++   __u8  bPatternReserved[6];
++   CSMI_SAS_CHARACTER UserPatternBuffer[16];
++} CSMI_SAS_PHY_CONTROL,
++  *PCSMI_SAS_PHY_CONTROL;
++
++typedef struct _CSMI_SAS_PHY_CONTROL_BUFFER {
++   IOCTL_HEADER IoctlHeader;
++   __u32 uFunction;
++   __u8  bPhyIdentifier;
++   __u16 usLengthOfControl;
++   __u8  bNumberOfControls;
++   __u8  bReserved[4];
++   __u32 uLinkFlags;
++   __u8  bSpinupRate;
++   __u8  bLinkReserved[7];
++   __u32 uVendorUnique[8];
++   CSMI_SAS_PHY_CONTROL Control[1];
++} CSMI_SAS_PHY_CONTROL_BUFFER,
++  *PCSMI_SAS_PHY_CONTROL_BUFFER;
++
++// EDN #pragma CSMI_SAS_END_PACK
++#pragma pack()
++
++#endif // _CSMI_SAS_H_
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/Makefile linux-2.6.9-55.0.12/drivers/message/fusion/Makefile
+--- linux-2.6.9-67.0.1/drivers/message/fusion/Makefile 2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/Makefile        2007-11-02 09:10:23.000000000 +0100
+@@ -8,8 +8,6 @@
+ #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
+ #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
+ #EXTRA_CFLAGS  += -DMPT_DEBUG_SAS
+-EXTRA_CFLAGS += -DCPQ_CIM
+-EXTRA_CFLAGS += -DMPT_SUPPORT_FWDLB_IOCTL
+ #
+ # driver/module specifics...
+@@ -31,6 +29,7 @@ EXTRA_CFLAGS += -DMPT_SUPPORT_FWDLB_IOCT
+ #
+ #  For mptctl:
+ #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
++CFLAGS_mptctl.o  += -DCPQ_CIM
+ #
+ #  For mptsas:
+ #CFLAGS_mptsas.o += -DMPT_DEBUG_HOTPLUG
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.c linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.c        2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.c       2007-11-02 09:10:23.000000000 +0100
+@@ -5,8 +5,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptbase.c,v 1.130 2003/05/07 14:08:30 Exp $
+  */
+@@ -93,8 +93,6 @@ MODULE_VERSION(MPT_LINUX_VERSION_COMMON)
+ char *mptbase = NULL;
+ /* Command line args */
+-
+-
+ int mpt_can_queue = 128;
+ module_param(mpt_can_queue, int, 0);
+ MODULE_PARM_DESC(mpt_can_queue, " Max IO depth per controller (default=128)");
+@@ -115,11 +113,6 @@ static int mpt_msi_enable = 0;
+ module_param(mpt_msi_enable, int, 0);
+ MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+-int mpt_enable_deadioc_detect = 0;
+-module_param(mpt_enable_deadioc_detect, int, 0);
+-MODULE_PARM_DESC(mpt_enable_deadioc_detect, "Detection of Dead IOC Enable (default=0)");
+-
+-//@@@@
+ #ifdef MFCNT
+ static int mfcounter = 0;
+ #define PRINT_MF_COUNT 20000
+@@ -163,13 +156,10 @@ static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq
+  */
+ static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
+ static int    mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
+-int   mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
++static int    mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
+                       u32 *req, int replyBytes, u16 *u16reply, int maxwait,
+                       int sleepFlag);
+-int                   mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
+-int             mpt_writeSDP1(MPT_ADAPTER *hd, int portnum, int id, int flags);
+-void    mpt_setSDP1parameters (u8 width, u8 factor, u8 offset, u8 flags, int *requestedPtr, int *configurationPtr);
+-
++static int    mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
+ static void   mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
+ static void   mpt_adapter_disable(MPT_ADAPTER *ioc);
+ static void   mpt_adapter_dispose(MPT_ADAPTER *ioc);
+@@ -187,7 +177,7 @@ static int mpt_do_upload(MPT_ADAPTER *io
+ int           mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
+ static int    mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
+ static int    KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
+-int             mpt_SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
++static int    SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
+ static int    PrimeIocFifos(MPT_ADAPTER *ioc);
+ static int    WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
+ static int    WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
+@@ -197,6 +187,9 @@ static int GetFcPortPage0(MPT_ADAPTER *i
+ static int    GetIoUnitPage2(MPT_ADAPTER *ioc);
+ static int    GetManufPage5(MPT_ADAPTER *ioc, int numPorts);
+ static int    GetManufPage0(MPT_ADAPTER *ioc);
++int           mpt_sas_get_info(MPT_ADAPTER *ioc);
++static void   mptbase_sas_process_event_data(MPT_ADAPTER *ioc,
++                  MpiEventDataSasDeviceStatusChange_t * pSasEventData);
+ int           mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+ static void   mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
+                   MpiEventDataRaid_t * pRaidEventData);
+@@ -204,7 +197,6 @@ static int mpt_GetScsiPortSettings(MPT_A
+ static int    mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
+ static void   mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
+ static void   mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
+-static void   mpt_read_ioc_pg_6(MPT_ADAPTER *ioc);
+ static void   mpt_timer_expired(unsigned long data);
+ static int    SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
+ static int    SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
+@@ -227,7 +219,6 @@ static void        mpt_sp_ioc_info(MPT_ADAPTER 
+ static void   mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
+ static void   mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
+ static void   mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
+-static void   mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
+ /* module entry point */
+ static int  __init    fusion_init  (void);
+@@ -273,10 +264,10 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa
+ {
+       MPT_FRAME_HDR *mf = NULL;
+       MPT_FRAME_HDR *mr = NULL;
+-      int req_idx;
++      int req_idx = 0;
+       int cb_idx;
+-      dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply pa=%08x\n",
++      dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
+                               ioc->name, pa));
+       switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
+@@ -312,9 +303,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa
+               break;
+       default:
+               cb_idx = 0;
+-              printk(MYIOC_s_WARN_FMT "%s: Invalid REPLY_TYPE in pa=%08x!\n",
+-                      __FUNCTION__, ioc->name, pa);
+-//            BUG();
++              BUG();
+       }
+       /*  Check for (valid) IO callback!  */
+@@ -342,12 +331,6 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+       u32 reply_dma_low;
+       u16 ioc_stat;
+-#ifdef MPT_DEBUG_REPLY
+-      u8  function;
+-      MPT_FRAME_HDR *chain;
+-      int chain_idx, chain_number, next;
+-#endif
+-
+       /* non-TURBO reply!  Hmmm, something may be up...
+        *  Newest turbo reply mechanism; get address
+@@ -367,44 +350,21 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+       cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
+       mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+-      ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
+-#ifdef MPT_DEBUG_REPLY
+-         if ((ioc_stat != MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE) && /* 0x0043 */
+-            (ioc_stat != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {    /* 0x0045 */
+-              function = mr->u.hdr.Function;
+-              dreplyprintk((MYIOC_s_WARN_FMT "non-TURBO reply context=%04x%04x Function=%x IOCStatus=%04x\n",
+-                      ioc->name, cb_idx, req_idx, function, ioc_stat));
+-              DBG_DUMP_REPLY_FRAME(mr)
+-
+-              printk("Request:\n");
+-                DBG_DUMP_REPLYS_REQUEST_FRAME(ioc, mf)
+-              chain_number = 1;
+-              chain_idx = ioc->ReqToChain[req_idx];
+-              while (chain_idx != MPT_HOST_NO_CHAIN) {
+-                      next = ioc->ChainToChain[chain_idx];
+-                      chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
+-                              + (chain_idx * ioc->req_sz));
+-                      printk("Chain %d:\n", chain_number++);
+-                        DBG_DUMP_REPLYS_REQUEST_FRAME(ioc, chain)
+-                      chain_idx = next;
+-              }
+-      }
+-#endif
++      dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
++                      ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
++      DBG_DUMP_REPLY_FRAME(mr)
+        /*  Check/log IOC log info
+        */
++      ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
+       if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+               u32      log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+               if (ioc->bus_type == FC)
+                       mpt_fc_log_info(ioc, log_info);
+               else if (ioc->bus_type == SPI)
+                       mpt_spi_log_info(ioc, log_info);
+-              else if (ioc->bus_type == SAS) {
+-                      printk(MYIOC_s_INFO_FMT
+-                              "IOCStatus=%04x LogInfo=%08x ",
+-                              ioc->name, ioc_stat, log_info);
++              else if (ioc->bus_type == SAS)
+                       mpt_sas_log_info(ioc, log_info);
+-              }
+       }
+       if (ioc_stat & MPI_IOCSTATUS_MASK) {
+               if (ioc->bus_type == SPI &&
+@@ -432,31 +392,6 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+       if (freeme)
+               mpt_free_msg_frame(ioc, mf);
+       mb();
+-if (ioc->CheckFcLinkSpeed &&
+-          ioc->FcLinkSpeedCheckNeeded &&
+-          ioc->FcLinkSpeedReqActive == NULL &&
+-          (mf = mpt_get_msg_frame(mpt_base_index, ioc))) {
+-              pConfig_t       pConfigMsg;
+-              dma_addr_t      physAddr;
+-
+-              ioc->FcLinkSpeedCheckNeeded = 0;
+-              ioc->FcLinkSpeedReqActive = mf;
+-              pConfigMsg = (pConfig_t)mf;
+-              /* there's enough room, so FCPortPage0 will be put in the mf */
+-              physAddr = ioc->req_frames_dma + sizeof(pConfig_t) +
+-                      (u8 *)mf - (u8 *)ioc->req_frames;
+-              memset(pConfigMsg, 0, ioc->req_sz);
+-              pConfigMsg->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-              pConfigMsg->Function = MPI_FUNCTION_CONFIG;
+-              pConfigMsg->Header.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
+-              pConfigMsg->Header.PageNumber = 0;
+-              pConfigMsg->Header.PageLength = sizeof(FCPortPage0_t) / 4;
+-              pConfigMsg->Header.PageVersion = MPI_FCPORTPAGE0_PAGEVERSION;
+-              mpt_add_sge((char *)&pConfigMsg->PageBufferSGE,
+-                      MPT_SGE_FLAGS_SSIMPLE_READ + sizeof(FCPortPage0_t),
+-                      physAddr);
+-              mpt_put_msg_frame(mpt_base_index, ioc, mf);
+-        }
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -543,17 +478,15 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
+               }
+               /*
+-               *       EventNotificationReply is an exception
++               *      Hmmm...  It seems that EventNotificationReply is an exception
+                *      to the rule of one reply per request.
+                */
+               if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
+                       freereq = 0;
+               } else {
+-                    devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns mf=%p evnp=%p\n", ioc->name, pEvReply, mf, ioc->evnp));
+-              if ( (MPT_FRAME_HDR *)ioc->evnp == mf ) {
+-                         ioc->evnp = NULL;
+-                   }
+- }
++                      devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
++                              ioc->name, pEvReply));
++              }
+ #ifdef CONFIG_PROC_FS
+ //            LogEvent(ioc, pEvReply);
+@@ -562,7 +495,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
+       } else if (func == MPI_FUNCTION_EVENT_ACK) {
+               dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
+                               ioc->name));
+-      } else if (func == MPI_FUNCTION_CONFIG ) {
++      } else if (func == MPI_FUNCTION_CONFIG) {
+               CONFIGPARMS *pCfg;
+               unsigned long flags;
+@@ -617,29 +550,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
+                        */
+                       pCfg->wait_done = 1;
+                       wake_up(&mpt_waitq);
+-              }else if (mf == ioc->FcLinkSpeedReqActive) {
+-     pFCPortPage0_t  pFCPortPage0 = (pFCPortPage0_t)((u8 *)mf + sizeof(pConfig_t));
+-                u8 OldSpeed = ioc->FcLinkSpeed;
+-              u8 NewSpeed = pFCPortPage0->CurrentSpeed;
+-              u8 State = pFCPortPage0->PortState;
+-                ioc->FcLinkSpeedReqActive = NULL;
+-                      if (State != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE &&
+-                          NewSpeed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) {
+-                              char    *old;
+-                              char    *new;
+- old = OldSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :OldSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :OldSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
+- "Unknown";
+-new = NewSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :NewSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
+-NewSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : "Unknown";
+-
+-if (OldSpeed == 0) { printk(MYIOC_s_NOTE_FMT "FC Link Established, Speed = %s\n", ioc->name, new);
+-      } else if (OldSpeed != NewSpeed)
+-{
+-printk(MYIOC_s_WARN_FMT "FC Link Speed Change, Old Speed = %s, New Speed = %s\n",ioc->name, old, new);
+-}
+-ioc->FcLinkSpeed = NewSpeed;
+-}
+-}
++              }
+       } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
+               /* we should be always getting a reply frame */
+               memcpy(ioc->persist_reply_frame, reply,
+@@ -868,10 +779,6 @@ MPT_FRAME_HDR*
+ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
+ {
+       MPT_FRAME_HDR *mf;
+-        #ifdef MPT_DEBUG_FAIL
+-          u8      *mem;
+-        #endif
+-
+       unsigned long flags;
+       u16      req_idx;       /* Request index */
+@@ -884,10 +791,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTE
+       /* If interrupts are not attached, do not return a request frame */
+       if (!ioc->active)
+-       {
+-            printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame!!\n");
+               return NULL;
+-       }
+       spin_lock_irqsave(&ioc->FreeQlock, flags);
+       if (!list_empty(&ioc->FreeQ)) {
+@@ -907,36 +811,10 @@ mpt_get_msg_frame(int handle, MPT_ADAPTE
+ #ifdef MFCNT
+               ioc->mfcnt++;
+ #endif
+-      } else {
+-#ifdef MPT_DEBUG_FAIL
+-dfailprintk((MYIOC_s_WARN_FMT "%s, No Free Message Frame!!\n",
+-     ioc->name,__FUNCTION__));
+-              mem = (u8 *) ioc->req_frames;
+-              for (req_idx = 0; req_idx < 10; req_idx++) {
+-      {
+-              u32     *m = (u32 *)(mem);
+-              int      ii, n;
+-
+-              printk(KERN_WARNING MYNAM ": %s: msg frame %d @ %p:\n" KERN_INFO " ",
+-                              ioc->name, req_idx, m);
+-              n = ioc->req_sz/4;
+-              for (ii=0; ii<n; ii++) {
+-                      if (ii && ((ii%8)==0))
+-                              printk("\n");
+-                      printk("%08x ", le32_to_cpu(m[ii]));
+-              }
+-              printk("\n");
+-          }
+-               mem += ioc->req_sz;
+-               }
+-#endif
+-
+-
+-
+-mf = NULL;
+-}
+-spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+-
++      }
++      else
++              mf = NULL;
++      spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+ #ifdef MFCNT
+       if (mf == NULL)
+@@ -984,13 +862,13 @@ mpt_put_msg_frame(int handle, MPT_ADAPTE
+               printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
+                               ioc->name, m);
+-              n = ioc->req_sz/4 ;
++              n = ioc->req_sz/4 - 1;
+               while (m[n] == 0)
+                       n--;
+               for (ii=0; ii<=n; ii++) {
+                       if (ii && ((ii%8)==0))
+                               printk("\n" KERN_INFO " ");
+-                      printk("%08x ", le32_to_cpu(m[ii]));
++                      printk(" %08x", le32_to_cpu(m[ii]));
+               }
+               printk("\n");
+       }
+@@ -1074,14 +952,16 @@ mpt_add_sge(char *pAddr, u32 flagslength
+  *    Returns 0 for success, non-zero for failure.
+  */
+ int
+-mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, ulong timeout, int sleepFlag)
++mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
+ {
+-      int     r = 0;
++      int              r = 0;
+       u8      *req_as_bytes;
+-      int     ii;
++      int      ii;
+-      dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request reqBytes=%d\n",
+-              ioc->name, reqBytes));
++      /* State is known to be good upon entering
++       * this function so issue the bus reset
++       * request.
++       */
+       /*
+        * Emulate what mpt_put_msg_frame() does /wrt to sanity
+@@ -1089,16 +969,12 @@ mpt_send_handshake_request(int handle, M
+        * is in proper (pre-alloc'd) request buffer range...
+        */
+       ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
+-      if (ii >= 0 && ii < ioc->req_depth) {
++      if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
+               MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
+               mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
+               mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
+       }
+-               ioc->tmPtr = (MPT_FRAME_HDR *)req;
+-               ioc->TMtimer.expires = jiffies + HZ*timeout;  /* seconds */
+-               add_timer(&ioc->TMtimer);
+-
+       /* Make sure there are no doorbells */
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+@@ -1108,25 +984,20 @@ mpt_send_handshake_request(int handle, M
+       /* Wait for IOC doorbell int */
+       if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
+-              r= ii;
+-                goto mpt_send_handshake_failed;
++              return ii;
+       }
+       /* Read doorbell and check for active bit */
+-      if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)){
+-              r= -5;
+-                goto mpt_send_handshake_failed;
+-           }
+-
++      if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
++              return -5;
+       dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
+               ioc->name, ii));
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+-        if ((WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+-            r=-2;
+-             goto mpt_send_handshake_failed;
++      if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
++              return -2;
+       }
+       /* Send request via doorbell handshake */
+@@ -1138,33 +1009,21 @@ mpt_send_handshake_request(int handle, M
+                       (req_as_bytes[(ii*4) + 1] <<  8) |
+                       (req_as_bytes[(ii*4) + 2] << 16) |
+                       (req_as_bytes[(ii*4) + 3] << 24));
+-dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request word=%08x ii=%d\n",ioc->name, word, ii));
+-
+               CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
+-              if ( WaitForDoorbellAck(ioc, 5, sleepFlag) < 0) {
++              if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+                       r = -3;
+-                      goto mpt_send_handshake_failed;
++                      break;
+               }
+       }
+-      dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request reqBytes=%d sent, WaitForDoorbellInt\n",
+-              ioc->name, reqBytes));
+-
+-      if ( WaitForDoorbellInt(ioc, 10, sleepFlag)< 0)
++      if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
++              r = 0;
++      else
+               r = -4;
+       /* Make sure there are no doorbells */
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+-mpt_send_handshake_failed:
+-      if (r < 0) {
+-              del_timer(&ioc->TMtimer);
+-              ioc->tmPtr = NULL;
+-      }
+-      dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request r=%d\n",
+-              ioc->name, r));
+-
+-
+       return r;
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -1186,6 +1045,7 @@ mpt_send_handshake_failed:
+ static int
+ mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
+ {
++      int      r = 0;
+       /* return if in use */
+       if (CHIPREG_READ32(&ioc->chip->Doorbell)
+@@ -1200,7 +1060,7 @@ mpt_host_page_access_control(MPT_ADAPTER
+                (access_control_value<<12)));
+       /* Wait for IOC to clear Doorbell Status bit */
+-      if (( WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
++      if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+               return -2;
+       }else
+               return 0;
+@@ -1344,10 +1204,20 @@ mpt_bringup_adapter(MPT_ADAPTER *ioc, in
+ {
+       int r;
++      if(ioc->alt_ioc) {
++              if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))
++                      return r;
++      }
+       r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
+           CAN_SLEEP);
++      if(ioc->alt_ioc) {
++              spin_lock(&ioc->alt_ioc->initializing_hba_lock);
++              ioc->alt_ioc->initializing_hba_lock_flag=0;
++              spin_unlock(&ioc->alt_ioc->initializing_hba_lock);
++      }
++
+ return r;
+ }
+@@ -1383,8 +1253,6 @@ mpt_attach(struct pci_dev *pdev, const s
+       u8               revision;
+       u8               pcixcmd;
+       static int       mpt_ids = 0;
+-        unsigned long flags;
+-
+ #ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *dent, *ent;
+ #endif
+@@ -1420,7 +1288,6 @@ mpt_attach(struct pci_dev *pdev, const s
+       ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
+       ioc->pcidev = pdev;
+-        ioc->IOCResetInProgress = 0;
+       ioc->diagPending = 0;
+       spin_lock_init(&ioc->diagLock);
+       spin_lock_init(&ioc->initializing_hba_lock);
+@@ -1596,17 +1463,10 @@ mpt_attach(struct pci_dev *pdev, const s
+       if(ioc->errata_flag_1064) {
+               pci_disable_io_access(pdev);
+       }
+-           if(ioc->bus_type == FC) {
+-               ioc->CheckFcLinkSpeed = 1;
+-               ioc->FcLinkSpeed = 0;
+-        }
+-
+       sprintf(ioc->name, "ioc%d", ioc->id);
+       spin_lock_init(&ioc->FreeQlock);
+-        spin_lock_init(&ioc->PendingMFlock);
+-
+       /* Disable all! */
+       CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+@@ -1659,43 +1519,22 @@ mpt_attach(struct pci_dev *pdev, const s
+        */
+       mpt_detect_bound_ports(ioc, pdev);
+-if(mpt_enable_deadioc_detect){
+-/* The following list initializations is moved from PrimeIocFifos
+-                because the lists will not get initialize for non-operational
+-                IOCs and which cause a crash when the lists are accessed later
+-                */
+-/* Initialize the free chain Q.*/
+-
+-        INIT_LIST_HEAD(&ioc->FreeChainQ);
+-        spin_lock_irqsave(&ioc->FreeQlock, flags);
+-        INIT_LIST_HEAD(&ioc->FreeQ);
+-        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+-        init_MUTEX(&ioc->raid_data.inactive_list_mutex);
+-        INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
+-
+-      /* Even If there is any error in IOC bringup, the IOC is allowed to
+-              be attached with MPT drivers, This change is done to support
+-              Firmware download boot functionality for FW dead IOC */
+-       mpt_bringup_adapter(ioc, CAN_SLEEP);
+-     }
+-
+-else {
+-        if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
+-            printk(KERN_WARNING MYNAM
+-               ": WARNING - %s did not initialize properly! (%d)\n",
+-               ioc->name, r);
+-               list_del(&ioc->list);
+-               free_irq(ioc->pci_irq, ioc);
+-               if (mpt_msi_enable == 1) {
+-                      pci_disable_msi(pdev);
+-               }
+-               iounmap(mem);
+-               kfree(ioc);
+-             pci_set_drvdata(pdev, NULL);
+-               return r;
++      if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
++              printk(KERN_WARNING MYNAM
++                ": WARNING - %s did not initialize properly! (%d)\n",
++                ioc->name, r);
++
++              list_del(&ioc->list);
++              free_irq(ioc->pci_irq, ioc);
++              if (mpt_msi_enable == 1) {
++                      pci_disable_msi(pdev);
++              }
++              iounmap(mem);
++              kfree(ioc);
++              pci_set_drvdata(pdev, NULL);
++              return r;
+       }
+-}
+       /* call per device driver probe entry point */
+       for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
+               if(MptDeviceDriverHandlers[ii] &&
+@@ -1812,7 +1651,7 @@ mpt_suspend(struct pci_dev *pdev, pm_mes
+ #endif
+       /* put ioc into READY_STATE */
+-      if(mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
++      if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
+               printk(MYIOC_s_ERR_FMT
+               "pci-suspend:  IOC msg unit reset failed!\n", ioc->name);
+       }
+@@ -1864,8 +1703,7 @@ mpt_resume(struct pci_dev *pdev)
+       if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
+               /* enable domain validation flags */
+               for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+-                      ioc->spi_data.dvStatus[ii] |= (MPT_SCSICFG_NEED_DV |
+-                                                             MPT_SCSICFG_DV_NOT_DONE);
++                      ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
+               }
+       }
+@@ -1905,19 +1743,23 @@ mpt_resume(struct pci_dev *pdev)
+  *
+  *    Returns:
+  *             0 for success
+- *            -1 if failed to get board READY
++ *            -1 if failed to get boardMODULE_VERSION(MPT_LINUX_VERSION_COMMON);
++ READY
+  *            -2 if READY but IOCFacts Failed
+  *            -3 if READY but PrimeIOCFifos Failed
+  *            -4 if READY but IOCInit Failed
+  */
+-int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
+-{       unsigned long flags;
++static int
++mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
++{
+       int      hard_reset_done = 0;
++      int      alt_ioc_ready = 0;
+       int      hard;
+       int      rc = 0;
+       int      ii;
++      int      handlers;
+       int      ret = 0;
+-
++      int      reset_alt_ioc_active = 0;
+       printk(KERN_INFO MYNAM ": Initiating %s %s\n",
+                       ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
+@@ -1926,15 +1768,13 @@ int mpt_do_ioc_recovery(MPT_ADAPTER *ioc
+       CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+       ioc->active = 0;
+-/* If an event notification has not returned
+- * its request frame,
+- * free resources associated with this request.
+- */
+-        if (ioc->evnp) {
+-            drsprintk((MYIOC_s_WARN_FMT "do_ioc_recovery: freeing evnp=%p\n",
+-                 ioc->name, ioc->evnp));
+-            mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)ioc->evnp);
+-            ioc->evnp = NULL;
++      if (ioc->alt_ioc) {
++              if (ioc->alt_ioc->active)
++                      reset_alt_ioc_active = 1;
++
++              /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
++              CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
++              ioc->alt_ioc->active = 0;
+       }
+       hard = 1;
+@@ -1945,39 +1785,68 @@ int mpt_do_ioc_recovery(MPT_ADAPTER *ioc
+               if (hard_reset_done == -4) {
+                       printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
+                                       ioc->name);
++
++                      if (reset_alt_ioc_active && ioc->alt_ioc) {
++                              /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
++                              dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
++                                              ioc->alt_ioc->name));
++                              CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
++                              ioc->alt_ioc->active = 1;
++                      }
++
+               } else {
+                       printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
+                                       ioc->name);
+               }
+-
+-               spin_lock_irqsave(&ioc->diagLock, flags);
+-               ioc->IOCResetInProgress = 0;
+-               spin_unlock_irqrestore(&ioc->diagLock, flags);
+               return -1;
+       }
++      /* hard_reset_done = 0 if a soft reset was performed
++       * and 1 if a hard reset was performed.
++       */
++      if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
++              if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
++                      alt_ioc_ready = 1;
++              else
++                      printk(KERN_WARNING MYNAM
++                                      ": alt-%s: Not ready WARNING!\n",
++                                      ioc->alt_ioc->name);
++      }
++
++      for (ii=0; ii<5; ii++) {
++              /* Get IOC facts! Allow 5 retries */
++              if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
++                      break;
++      }
+-if (reason == MPT_HOSTEVENT_IOC_BRINGUP ||
+-                        mpt_enable_deadioc_detect){
+-             for (ii=0; ii<5; ii++) {
+-                /* Get IOC facts! Allow 5 retries */
+-                   if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
+-                               break;
+-}
++      if (ii == 5) {
++              dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
++              ret = -2;
++      } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
++              MptDisplayIocCapabilities(ioc);
++      }
+-if(ii==5) {
+-dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name , rc));
+-             ret = -2;
+-        } else {
+-       if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
+-         MptDisplayIocCapabilities(ioc);
++      if (alt_ioc_ready) {
++              if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
++                      dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
++                      /* Retry - alt IOC was initialized once
++                       */
++                      rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
++              }
++              if (rc) {
++                      dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
++                      alt_ioc_ready = 0;
++                      reset_alt_ioc_active = 0;
++              } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
++                      MptDisplayIocCapabilities(ioc->alt_ioc);
+               }
+       }
+       /* Prime reply & request queues!
+        * (mucho alloc's) Must be done prior to
+        * init as upper addresses are needed for init.
++       * If fails, continue with alt-ioc processing
+        */
+       if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
+               ret = -3;
+@@ -1987,6 +1856,23 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+        */
+       if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
+               ret = -4;
++// NEW!
++      if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
++              printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
++                              ioc->alt_ioc->name, rc);
++              alt_ioc_ready = 0;
++              reset_alt_ioc_active = 0;
++      }
++
++      if (alt_ioc_ready) {
++              if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
++                      alt_ioc_ready = 0;
++                      reset_alt_ioc_active = 0;
++                      printk(KERN_WARNING MYNAM
++                              ": alt-%s: (%d) init failure WARNING!\n",
++                                      ioc->alt_ioc->name, rc);
++              }
++      }
+       if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
+               if (ioc->upload_fw) {
+@@ -2024,6 +1910,13 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+               ioc->active = 1;
+       }
++      if (reset_alt_ioc_active && ioc->alt_ioc) {
++              /* (re)Enable alt-IOC! (reply interrupt) */
++              dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
++                              ioc->alt_ioc->name));
++              CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
++              ioc->alt_ioc->active = 1;
++      }
+       /*  Enable MPT base driver management of EventNotification
+        *  and EventAck handling.
+@@ -2031,6 +1924,9 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+       if ((ret == 0) && (!ioc->facts.EventState))
+               (void) SendEventNotification(ioc, 1);   /* 1=Enable EventNotification */
++      if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
++              (void) SendEventNotification(ioc->alt_ioc, 1);  /* 1=Enable EventNotification */
++
+       /*      Add additional "reason" check before call to GetLanConfigPages
+        *      (combined with GetIoUnitPage2 call).  This prevents a somewhat
+        *      recursive scenario; GetLanConfigPages times out, timer expired
+@@ -2038,30 +1934,32 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+        *      and we try GetLanConfigPages again...
+        */
+       if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
+-
+-              /*
+-               * Initalize link list for inactive raid volumes.
+-               */
+-              init_MUTEX(&ioc->raid_data.inactive_list_mutex);
+-              INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
+-
+               if (ioc->bus_type == SAS) {
++
+                       /*
+                        * Pre-fetch SAS Address for each port
+                        */
+                       GetManufPage5(ioc, ioc->facts.NumberOfPorts);
++                      /*
++                       * Pre-fetch Serial number for the board.
++                       */
++                      GetManufPage0(ioc);
++
++                      /*
++                       * Pre-fetch Hw Link Rates. (These may get
++                       * overwritten so need to save them.)
++                       * Save other SAS data needed for Ioctls.
++                       */
++                      mpt_sas_get_info(ioc);
++
+                       /* clear persistency table */
+                       if(ioc->facts.IOCExceptions &
+                           MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
+                               ret = mptbase_sas_persist_operation(ioc,
+                                   MPI_SAS_OP_CLEAR_NOT_PRESENT);
+-                              if(ret != 0){
+-                                 spin_lock_irqsave(&ioc->diagLock, flags);
+-                                       ioc->IOCResetInProgress = 0;
+-                                       spin_unlock_irqrestore(&ioc->diagLock, flags);
++                              if(ret != 0)
+                                       return -1;
+-                                        }
+                       }
+                       /* Find IM volumes
+@@ -2118,11 +2016,6 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+               }
+               GetIoUnitPage2(ioc);
+-
+-              /*
+-               * Pre-fetch Serial number for the board.
+-               */
+-              GetManufPage0(ioc);
+       }
+       /*
+@@ -2131,35 +2024,26 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc
+        * NOTE: If we're doing _IOC_BRINGUP, there can be no
+        * MptResetHandlers[] registered yet.
+        */
+-               if (ret == 0) {
+-                       rc = 0;
+-
+-               for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+-                         if (MptResetHandlers[ii]) {
+-       drsprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\ n",ioc->name, ii));
+-
++      if (hard_reset_done) {
++              rc = handlers = 0;
++              for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
++                      if ((ret == 0) && MptResetHandlers[ii]) {
++                              dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
++                                              ioc->name, ii));
+                               rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
++                              handlers++;
++                      }
++                      if (alt_ioc_ready && MptResetHandlers[ii]) {
++                              drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
++                                              ioc->name, ioc->alt_ioc->name, ii));
++                              rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
++                              handlers++;
+                       }
+               }
++              /* FIXME?  Examine results here? */
+       }
+-if (ioc->bus_type == FC) {
+-              ioc->FcLinkSpeedCheckNeeded = 1;
+-      }
+-
+-      if (ioc->bus_type == SPI) {
+-              drsprintk((MYIOC_s_WARN_FMT "%s: calling writeSDP1: ALL_IDS USE_NVRAM\n",
+-                      ioc->name, __FUNCTION__));
+-              dnegoprintk((MYIOC_s_WARN_FMT "%s: calling writeSDP1: ALL_IDS USE_NVRAM\n",
+-                      ioc->name, __FUNCTION__));
+-              mpt_writeSDP1(ioc, 0, 0, (MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM));
+-      }
+-
+-      spin_lock_irqsave(&ioc->diagLock, flags);
+-      ioc->IOCResetInProgress = 0;
+-      spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+       return ret;
+ }
+@@ -2224,11 +2108,9 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc,
+ static void
+ mpt_adapter_disable(MPT_ADAPTER *ioc)
+ {
+-      struct _MPT_DEVICE      *pMptTarget;
+-      VirtDevice              *pTarget;
++      sas_device_info_t *sasDevice, * pNext;
+       int sz;
+       int ret, ii;
+-      int bus, id;
+       void *                  request_data;
+       dma_addr_t              request_data_dma;
+       u32                     request_data_sz;
+@@ -2253,7 +2135,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+               if ( request_data ) {
+                       request_data_sz = ioc->DiagBuffer_sz[ii];
+                       request_data_dma = ioc->DiagBuffer_dma[ii];
+-                      dexitprintk((KERN_INFO MYNAM ": %s: free DiagBuffer[%d] @ %p, sz=%d bytes\n",
++                      dexitprintk((KERN_INFO MYNAM ": %s free DiagBuffer[%d] @ %p, sz=%d bytes\n",
+                               ioc->name, ii, request_data, request_data_sz));
+                       pci_free_consistent(ioc->pcidev, request_data_sz,
+                               request_data,
+@@ -2264,7 +2146,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+       }
+       if (ioc->alloc != NULL) {
+               sz = ioc->alloc_sz;
+-              dexitprintk((KERN_INFO MYNAM ": %s: free alloc @ %p, sz=%d bytes\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free alloc @ %p, sz=%d bytes\n",
+                       ioc->name, ioc->alloc, ioc->alloc_sz));
+               pci_free_consistent(ioc->pcidev, sz,
+                               ioc->alloc, ioc->alloc_dma);
+@@ -2276,7 +2158,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+       if (ioc->sense_buf_pool != NULL) {
+               sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
+-              dexitprintk((KERN_INFO MYNAM ": %s: free sense_buf_pool @ %p, sz=%d bytes\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free sense_buf_pool @ %p, sz=%d bytes\n",
+                       ioc->name, ioc->sense_buf_pool, sz));
+               pci_free_consistent(ioc->pcidev, sz,
+                               ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
+@@ -2286,7 +2168,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+       if (ioc->events != NULL){
+               sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
+-              dexitprintk((KERN_INFO MYNAM ": %s: free events @ %p, sz=%d bytes\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free events @ %p, sz=%d bytes\n",
+                       ioc->name, ioc->events, sz));
+               kfree(ioc->events);
+               ioc->events = NULL;
+@@ -2295,7 +2177,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+       if (ioc->cached_fw != NULL) {
+               sz = ioc->facts.FWImageSize;
+-              dexitprintk((KERN_INFO MYNAM ": %s: free cached_fw @ %p, sz=%d bytes\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free cached_fw @ %p, sz=%d bytes\n",
+                       ioc->name, ioc->cached_fw, sz));
+               pci_free_consistent(ioc->pcidev, sz,
+                       ioc->cached_fw, ioc->cached_fw_dma);
+@@ -2304,29 +2186,22 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+       }
+       if (ioc->spi_data.nvram != NULL) {
+-              dexitprintk((KERN_INFO MYNAM ": %s: free spi_data.nvram @ %p\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free spi_data.nvram @ %p\n",
+                       ioc->name, ioc->spi_data.nvram));
+               kfree(ioc->spi_data.nvram);
+               ioc->spi_data.nvram = NULL;
+       }
+       if (ioc->raid_data.pIocPg3 != NULL) {
+-              dexitprintk((KERN_INFO MYNAM ": %s: free spi_data.pIocPg3 @ %p\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free spi_data.pIocPg3 @ %p\n",
+                       ioc->name, ioc->raid_data.pIocPg3));
+               kfree(ioc->raid_data.pIocPg3);
+               ioc->raid_data.pIocPg3 = NULL;
+       }
+-      if (ioc->raid_data.pIocPg6 != NULL) {
+-              dexitprintk((KERN_INFO MYNAM ": %s: free raid_data.pIocPg6 @ %p\n",
+-                      ioc->name, ioc->raid_data.pIocPg6));
+-              kfree(ioc->raid_data.pIocPg6);
+-              ioc->raid_data.pIocPg6 = NULL;
+-      }
+-
+       if (ioc->spi_data.pIocPg4 != NULL) {
+               sz = ioc->spi_data.IocPg4Sz;
+-              dexitprintk((KERN_INFO MYNAM ": %s: free spi_data.pIocPg4 @ %p size=%d\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free spi_data.pIocPg4 @ %p size=%d\n",
+                       ioc->name, ioc->spi_data.pIocPg4, sz));
+               pci_free_consistent(ioc->pcidev, sz,
+                       ioc->spi_data.pIocPg4,
+@@ -2336,41 +2211,38 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+       }
+       if (ioc->ReqToChain != NULL) {
+-              dexitprintk((KERN_INFO MYNAM ": %s: free ReqToChain @ %p\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free ReqToChain @ %p\n",
+                       ioc->name, ioc->ReqToChain));
+               kfree(ioc->ReqToChain);
+               ioc->ReqToChain = NULL;
+       }
+       if (ioc->RequestNB != NULL) {
+-              dexitprintk((KERN_INFO MYNAM ": %s: free RequestNB @ %p\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free RequestNB @ %p\n",
+                       ioc->name, ioc->RequestNB));
+               kfree(ioc->RequestNB);
+               ioc->RequestNB = NULL;
+       }
+       if (ioc->ChainToChain != NULL) {
+-              dexitprintk((KERN_INFO MYNAM ": %s: free ChainToChain @ %p\n",
++              dexitprintk((KERN_INFO MYNAM ": %s free ChainToChain @ %p\n",
+                       ioc->name, ioc->ChainToChain));
+               kfree(ioc->ChainToChain);
+               ioc->ChainToChain = NULL;
+       }
+-      mpt_inactive_raid_list_free(ioc);
++      list_for_each_entry_safe(sasDevice, pNext, &ioc->sasDeviceList, list) {
++              list_del(&sasDevice->list);
++              dexitprintk((KERN_INFO MYNAM ": %s free sasDevice @ %p\n",
++                      ioc->name, sasDevice));
++              kfree(sasDevice);
++      }
+-      for (bus = 0; bus < ioc->NumberOfBuses; bus++) {
+-              if ((pMptTarget = ioc->Target_List[bus])) {
+-                      for (id = 0; id < ioc->DevicesPerBus; id++) {
+-                              if ((pTarget = pMptTarget->Target[id])) {
+-                                      dexitprintk((KERN_INFO MYNAM ": %s: free bus=%d id=%d pTarget=%p\n",
+-                                              ioc->name, bus, id, pTarget));
+-                                      kfree (pTarget);
+-                              }
+-                      }
+-                      dexitprintk((KERN_INFO MYNAM ": %s: free bus=%d pMptTarget=%p\n",
+-                              ioc->name, bus, pMptTarget));
+-                      kfree (pMptTarget);
+-              }
++      if (ioc->sasPhyInfo != NULL) {
++              dexitprintk((KERN_INFO MYNAM ": %s free sasPhyInfo @ %p\n",
++                      ioc->name, ioc->sasPhyInfo));
++              kfree(ioc->sasPhyInfo);
++              ioc->sasPhyInfo = NULL;
+       }
+ /* emoore@lsil.com : Host Page Buffer Suport, start */
+@@ -2381,7 +2253,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
+                          ": %s: host page buffers free failed (%d)!\n",
+                           __FUNCTION__, ret);
+               }
+-              dexitprintk((KERN_INFO MYNAM ": %s: HostPageBuffer free  @ %p, sz=%d bytes\n",
++              dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free  @ %p, sz=%d bytes\n",
+                       ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
+               pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
+                               ioc->HostPageBuffer,
+@@ -2441,7 +2313,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
+       dexitprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
+               ioc->name, sz_first-sz_last+(int)sizeof(MPT_ADAPTER), sz_first));
+       dexitprintk((KERN_INFO MYNAM ": %s: sz_first=%d sz_last=%d sizeof(MPT_ADAPTER)=%d\n",
+-              ioc->name, sz_first, sz_last, (int)sizeof(MPT_ADAPTER)));
++              ioc->name, sz_first, sz_last, sizeof(MPT_ADAPTER)));
+       if (ioc->alt_ioc)
+               ioc->alt_ioc->alt_ioc = NULL;
+@@ -2521,17 +2393,12 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
+       /* Get current [raw] IOC state  */
+       ioc_state = mpt_GetIocState(ioc, 0);
+-      drsprintk((KERN_INFO MYNAM ": %s : MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
++      dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
+       for ( ii = 0; ii < MPI_DIAG_BUF_TYPE_COUNT; ii++) {
+               ioc->DiagBuffer[ii] = NULL;
+               ioc->DiagBuffer_Status[ii] = 0;
+       }
+-if (ioc->bus_type == FC) {
+-      ioc->FcLinkSpeedCheckNeeded = 0;
+-      ioc->FcLinkSpeedReqActive = NULL;
+-}
+-
+       /*
+        *      Check to see if IOC got left/stuck in doorbell handshake
+@@ -2544,12 +2411,9 @@ if (ioc->bus_type == FC) {
+       }
+       /* Is it already READY? */
+-      if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)  {
+-drsprintk((KERN_INFO MYNAM ": %s : MakeIocReady ioc_state=%08x = READY\n", ioc->name, ioc_state));
+-             /* Dont return for SAS IOCs */
+-             if (ioc->bus_type != SAS)
+-               return 0;
+-              }
++      if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) 
++              return 0;
++
+       /*
+        *      Check to see if IOC is in FAULT state.
+        */
+@@ -2581,7 +2445,7 @@ drsprintk((KERN_INFO MYNAM ": %s : MakeI
+                       return -4;
+               else {
+                       if ((statefault == 0 ) && (force == 0)) {
+-if ((r = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
++                              if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
+                                       return 0;
+                       }
+                       statefault = 3;
+@@ -2604,7 +2468,7 @@ if ((r = mpt_SendIocReset(ioc, MPI_FUNCT
+                        *  BIOS or previous driver load left IOC in OP state.
+                        *  Reset messaging FIFOs.
+                        */
+-if ((r = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
++                      if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
+                               printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
+                               return -2;
+                       }
+@@ -2613,7 +2477,7 @@ if ((r = mpt_SendIocReset(ioc, MPI_FUNCT
+                        *  Something is wrong.  Try to get IOC back
+                        *  to a known state.
+                        */
+-if ((r = mpt_SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
++                      if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
+                               printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
+                               return -3;
+                       }
+@@ -2629,7 +2493,7 @@ if ((r = mpt_SendIocReset(ioc, MPI_FUNCT
+               if (sleepFlag == CAN_SLEEP)
+                       msleep_interruptible(1);
+               else
+-                      MPT_MDELAY(1);  /* 1 msec delay */
++                      MPT_MDELAY(1);  /* 1 msec delay */
+       }
+@@ -2766,9 +2630,6 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
+                       facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
+               facts->ProductID = le16_to_cpu(facts->ProductID);
+-              if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+-                  > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
+-                      ioc->ir_firmware = 1;
+               facts->CurrentHostMfaHighAddr =
+                               le32_to_cpu(facts->CurrentHostMfaHighAddr);
+               facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
+@@ -2814,9 +2675,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
+               dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
+                                       ioc->name, vv, shiftFactor, r));
+-/* Allow dead IOCs to get detected after FWDLB*/
+- if (reason == MPT_HOSTEVENT_IOC_BRINGUP ||mpt_enable_deadioc_detect) {
+-
++              if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
+                       /*
+                        * Set values for this IOC's request & reply frame sizes,
+                        * and request & reply queue depths...
+@@ -2870,7 +2729,6 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn
+       int                      ii;
+       int                      req_sz;
+       int                      reply_sz;
+-      int                      max_id;
+       /* IOC *must* NOT be in RESET state! */
+       if (ioc->last_state == MPI_IOC_STATE_RESET) {
+@@ -2913,31 +2771,6 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn
+       pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
+       pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
+       pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
+-
+-      switch (ioc->bus_type) {
+-      case SAS:
+-              max_id = pfacts->PortSCSIID;
+-              break;
+-      case FC:
+-              max_id = pfacts->MaxDevices;
+-              break;
+-      case SPI:
+-      default:
+-              max_id = MPT_MAX_SCSI_DEVICES;
+-              break;
+-      }
+-
+-      ioc->DevicesPerBus = (max_id > 255) ? 256 : max_id;
+-      ioc->NumberOfBuses = (ioc->DevicesPerBus < 256) ? 1 : max_id/256;
+-      if ( ioc->NumberOfBuses > MPT_MAX_BUSES ) {
+-              dinitprintk((MYIOC_s_WARN_FMT "NumberOfBuses=%d > MPT_MAX_BUSES=%d\n",
+-                 ioc->name, ioc->NumberOfBuses, MPT_MAX_BUSES));
+-              ioc->NumberOfBuses = MPT_MAX_BUSES;
+-      }
+-
+-      dinitprintk((MYIOC_s_WARN_FMT "Buses=%d MaxDevices=%d DevicesPerBus=%d\n",
+-                 ioc->name, ioc->NumberOfBuses, max_id, ioc->DevicesPerBus));
+-
+       pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
+       pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
+       pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
+@@ -2983,11 +2816,15 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
+       dinitprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
+                  ioc->name, ioc->upload_fw, ioc->facts.Flags));
+-      ioc_init.MaxDevices = ioc->DevicesPerBus;
+-      ioc_init.MaxBuses = ioc->NumberOfBuses;
+-
+-      dinitprintk((MYIOC_s_INFO_FMT "ioc_init.MaxDevices=%d MaxBuses=%d\n",
+-                 ioc->name, ioc_init.MaxDevices, ioc_init.MaxBuses));
++      if(ioc->bus_type == SAS)
++              ioc_init.MaxDevices = ioc->facts.MaxDevices;
++      else if(ioc->bus_type == FC)
++              ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
++      else
++              ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
++      ioc_init.MaxBuses = MPT_MAX_BUS;
++      dinitprintk((MYIOC_s_INFO_FMT "ioc_init.MaxDevice=%d\n",
++                 ioc->name, ioc_init.MaxDevices));
+       dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
+                  ioc->name, ioc->facts.MsgVersion));
+ /* emoore@lsil.com : Host Page Buffer Suport, start */
+@@ -3110,7 +2947,9 @@ SendPortEnable(MPT_ADAPTER *ioc, int por
+       /* RAID FW may take a long time to enable
+        */
+-      if (ioc->ir_firmware || ioc->bus_type == SAS) {
++      if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
++          > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
++          (ioc->bus_type == SAS)) {
+               rc = mpt_handshake_req_reply_wait(ioc, req_sz,
+               (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
+               300 /*seconds*/, sleepFlag);
+@@ -3151,7 +2990,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
+       int sz;
+       sz = ioc->facts.FWImageSize;
+-      dinitprintk((KERN_INFO MYNAM ": free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
++      dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+                ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
+       pci_free_consistent(ioc->pcidev, sz,
+                       ioc->cached_fw, ioc->cached_fw_dma);
+@@ -3285,43 +3124,14 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
+       u32                      diag0val;
+       int                      count;
+       u32                     *ptrFw;
+-      u32                      diagRwData,doorbell;
++      u32                      diagRwData;
+       u32                      nextImage;
+       u32                      load_addr;
++      u32                      ioc_state=0;
+-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: pFwHeader=%p\n",ioc->name, pFwHeader));
+-      nextImage = pFwHeader->NextImageHeaderOffset;
+-      if (ioc->bus_type == SAS) {
+-              while (nextImage) {
+-                      if ( (pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage)) ) {
+-                              ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SAS nextImage=%x pExtImage=%p ImageType=%x\n",
+-                                      ioc->name, nextImage, pExtImage,
+-                                      pExtImage->ImageType));
+-                      } else {
+-                              ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SAS nextImage=%x pExtImage=%p is NULL!\n",
+-                                      ioc->name, nextImage, pExtImage));
+-                              return -EFAULT;
+-                      }
+-
+-                      if ( pExtImage->ImageType == MPI_EXT_IMAGE_TYPE_BOOTLOADER ) {
+-                              fwSize = (pExtImage->ImageSize + 3)/4;
+-                              ptrFw = (u32 *) pExtImage;
+-                              load_addr = pExtImage->LoadStartAddress;
+-                              goto imageFound;
+-                      }
+-                      nextImage = pExtImage->NextImageHeaderOffset;
+-              }
+-              ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SAS BOOTLOADER not found\n",
+-                      ioc->name));
+-              /* Allow this image to be downloaded */
+-      }
+-      fwSize = (pFwHeader->ImageSize + 3)/4;
+-      ptrFw = (u32 *) pFwHeader;
+-      load_addr = pFwHeader->LoadStartAddress;
++      ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
++                              ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
+-imageFound:
+-      ddlprintk((MYIOC_s_WARN_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p load_addr=%x\n",
+-              ioc->name, fwSize, fwSize, ptrFw, load_addr));
+       CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+       CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
+@@ -3345,7 +3155,7 @@ imageFound:
+       for (count = 0; count < 30; count ++) {
+               diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+               if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
+-                      ddlprintk((MYIOC_s_WARN_FMT "RESET_ADAPTER cleared, count=%d\n",
++                      ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
+                               ioc->name, count));
+                       break;
+               }
+@@ -3357,7 +3167,7 @@ imageFound:
+       }
+       if ( count == 30 ) {
+-              ddlprintk((MYIOC_s_WARN_FMT "downloadboot failed! Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
++              ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
+               ioc->name, diag0val));
+               return -3;
+       }
+@@ -3370,9 +3180,10 @@ imageFound:
+       CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+       /* Set the DiagRwEn and Disable ARM bits */
++      CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
+-        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
++      fwSize = (pFwHeader->ImageSize + 3)/4;
++      ptrFw = (u32 *) pFwHeader;
+       /* Write the LoadStartAddress to the DiagRw Address Register
+        * using Programmed IO
+@@ -3380,28 +3191,26 @@ CHIPREG_WRITE32(&ioc->chip->Diagnostic, 
+       if(ioc->errata_flag_1064) {
+               pci_enable_io_access(ioc->pcidev);
+       }
+-CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
++      CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
++      ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
++              ioc->name, pFwHeader->LoadStartAddress));
+-ddlprintk((MYIOC_s_WARN_FMT "LoadStart addr written 0x%x \n",ioc->name, load_addr));
+-ddlprintk((MYIOC_s_WARN_FMT "Write FW Image: 0x%x (%d) bytes @ %p\n",
+-                                ioc->name, fwSize*4, fwSize*4, ptrFw));
++      ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x (%d) bytes @ %p\n",
++                              ioc->name, fwSize*4, fwSize*4, ptrFw));
+       while (fwSize--) {
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
+       }
+-      if (ioc->bus_type == SAS) {
+-              pFwHeader->IopResetVectorValue = load_addr + 0x18;
+-      } else {
+-
+-              while (nextImage) {
+-                      pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
++      nextImage = pFwHeader->NextImageHeaderOffset;
++      while (nextImage) {
++              pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
+               load_addr = pExtImage->LoadStartAddress;
+               fwSize = (pExtImage->ImageSize + 3) >> 2;
+               ptrFw = (u32 *)pExtImage;
+-              ddlprintk((MYIOC_s_WARN_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
++              ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
+                                               ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
+@@ -3411,18 +3220,20 @@ ddlprintk((MYIOC_s_WARN_FMT "Write FW Im
+               nextImage = pExtImage->NextImageHeaderOffset;
+       }
+- }
+       /* Write the IopResetVectorRegAddr */
+-      ddlprintk((MYIOC_s_WARN_FMT "Write IopResetVector Addr=%x! \n", ioc->name,      pFwHeader->IopResetRegAddr));
++      ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name,      pFwHeader->IopResetRegAddr));
+       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
+       /* Write the IopResetVectorValue */
+-      ddlprintk((MYIOC_s_WARN_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
++      ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
+       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
++      /* Clear the internal flash bad bit - autoincrementing register,
++       * so must do two writes.
++       */
+       if (ioc->bus_type == SPI) {
+               /*
+-               * 1030 H/W errata, workaround to access
++               * 1030 and 1035 H/W errata, workaround to access
+                * the ClearFlashBadSignatureBit
+                */
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+@@ -3431,6 +3242,16 @@ ddlprintk((MYIOC_s_WARN_FMT "Write FW Im
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
++      } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
++              diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
++              CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
++                  MPI_DIAG_CLEAR_FLASH_BAD_SIG);
++
++              /* wait 1 msec */
++              if (sleepFlag == CAN_SLEEP)
++                      msleep_interruptible(1);
++              else
++                      MPT_MDELAY(1);
+       }
+       if(ioc->errata_flag_1064) {
+@@ -3438,77 +3259,48 @@ ddlprintk((MYIOC_s_WARN_FMT "Write FW Im
+       }
+       diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-      ddlprintk((MYIOC_s_WARN_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
++      ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
+               ioc->name, diag0val));
+-
+-diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
+-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: now diag0val=%x\n",
++      diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
++      ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
+               ioc->name, diag0val));
+       CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+-if (ioc->bus_type == SAS ) {
+-/* wait 1 sec */
+-if (sleepFlag == CAN_SLEEP)
+-{
+-msleep_interruptible(1000);
+-
+-}
+-else
+-MPT_MDELAY(1000);
+-
+-
+-
++      /* Write 0xFF to reset the sequencer */
++      CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: diag0val=%x, turning off RW_ENABLE\n"
+-            ioc->name, diag0val));
+-diag0val &= ~(MPI_DIAG_RW_ENABLE);
+-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: now diag0val=%x\n",
+-                   ioc->name, diag0val));
+-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-if (diag0val & MPI_DIAG_FLASH_BAD_SIG) {
+-diag0val |= MPI_DIAG_CLEAR_FLASH_BAD_SIG;
+-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
++      if (ioc->bus_type == SAS) {
++              ioc_state = mpt_GetIocState(ioc, 0);
++              if ( (GetIocFacts(ioc, sleepFlag,
++                              MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
++                      ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
++                                      ioc->name, ioc_state));
++                      return -EFAULT;
+               }
+-diag0val &= ~(MPI_DIAG_DISABLE_ARM);
+-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+-CHIPREG_WRITE32(&ioc->chip->DiagRwAddress, 0x3f000004);
+       }
+-/* Write 0xFF to reset the sequencer */
+-CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+-
+-        for (count = 0; count < 30; count ++) {
+-           doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
+-           doorbell &= MPI_IOC_STATE_MASK;
+-
+-                   if (doorbell == MPI_IOC_STATE_READY) {
++      for (count=0; count<HZ*20; count++) {
++              if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
++                      ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
++                                      ioc->name, count, ioc_state));
+                       if (ioc->bus_type == SAS) {
+                               return 0;
+                       }
+-
+-
+-      if ((SendIocInit(ioc, sleepFlag)) != 0) {
+-                              ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SendIocInit failed\n",
++                      if ((SendIocInit(ioc, sleepFlag)) != 0) {
++                              ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
+                                       ioc->name));
+                               return -EFAULT;
+                       }
+-                      ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SendIocInit successful\n",
++                      ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
+                                       ioc->name));
+                       return 0;
+               }
+-       ddlprintk((MYIOC_s_WARN_FMT "downloadboot: looking for READY STATE:doorbell=%x count=%d\n",ioc->name, doorbell, count));
+-                     /* wait 1 sec */
+-
+               if (sleepFlag == CAN_SLEEP)
+-                      msleep_interruptible(1000);
++                      msleep_interruptible(10);
+               else
+-                      MPT_MDELAY(1000);
++                      MPT_MDELAY(10);
+       }
+-      ddlprintk((MYIOC_s_WARN_FMT "downloadboot failed! IocState=%x\n",
++      ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
+               ioc->name, ioc_state));
+       return -EFAULT;
+ }
+@@ -3552,7 +3344,8 @@ KickStart(MPT_ADAPTER *ioc, int force, i
+               /* Always issue a Msg Unit Reset first. This will clear some
+                * SCSI bus hang conditions.
+                */
+-            mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
++              SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
++
+               if (sleepFlag == CAN_SLEEP)
+                       msleep_interruptible(1000);
+               else
+@@ -3624,26 +3417,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
+                       msleep_interruptible(1);
+               else
+                       MPT_MDELAY(1);
+-/*
+-               * Call each currently registered protocol IOC reset handler
+-               * with post-reset indication.
+-               * NOTE: If we're doing _IOC_BRINGUP, there can be no
+-               * MptResetHandlers[] registered yet.
+- */
+-                  {
+-                      int      ii;
+-                      int        r=0;
+-
+-                  for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+-                              if (MptResetHandlers[ii]) {
+-  drsprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",ioc->name, ii));
+-  r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
+-
+-   }
+-}
+-/* FIXME?  Examine results here? */
+-
+-}
+               for (count = 0; count < 60; count ++) {
+                       doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
+@@ -3746,11 +3519,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
+                       for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+                               if (MptResetHandlers[ii]) {
+-                                      drsprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
++                                      dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
+                                                       ioc->name, ii));
+                                       r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
+                                       if (ioc->alt_ioc) {
+-                                              drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
++                                              dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
+                                                               ioc->name, ioc->alt_ioc->name, ii));
+                                               r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
+                                       }
+@@ -3901,31 +3674,18 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
+  *
+  *    Returns 0 for success, non-zero for failure.
+  */
+-int
+-mpt_SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
++static int
++SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
+ {
+-        unsigned long flags;
+       int r;
+-      u32 state, Doorbell;
++      u32 state;
+       int cntdn, count;
+-Doorbell = (reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
+-
+-drsprintk((MYIOC_s_WARN_FMT ": %s: reset_type=%02x Doorbell=%08x!\n",
+-ioc->name, __FUNCTION__, reset_type, Doorbell));
+-CHIPREG_WRITE32(&ioc->chip->Doorbell, Doorbell);
+-
+-if ((r = WaitForDoorbellAck(ioc, 15, sleepFlag)) < 0){
+-                drsprintk((MYIOC_s_WARN_FMT ": %s: WaitForDoorbellAck failed r=%d after IOC Rese
+-t type=%02x!\n",
+-                        ioc->name, __FUNCTION__, r, reset_type));
+- return r;
+-}
+-
+-spin_lock_irqsave(&ioc->diagLock, flags);
+-ioc->IOCResetInProgress = 1;
+-spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
++      drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
++                      ioc->name, reset_type));
++      CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
++      if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
++              return r;
+       /* FW ACK'd request, wait for READY state
+        */
+@@ -3950,13 +3710,13 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+                       MPT_MDELAY(1);  /* 1 msec delay */
+       }
++      /* TODO!
++       *  Cleanup all event stuff for this IOC; re-issue EventNotification
++       *  request if needed.
++       */
+       if (ioc->facts.Function)
+               ioc->facts.EventState = 0;
+-spin_lock_irqsave(&ioc->diagLock, flags);
+-ioc->IOCResetInProgress = 0;
+-spin_unlock_irqrestore(&ioc->diagLock, flags);
+-drsprintk((MYIOC_s_WARN_FMT ": %s: IOC reset completed successfully state=%08x count=%d\ n",
+-ioc->name, __FUNCTION__, state, count));
++
+       return 0;
+ }
+@@ -4044,9 +3804,8 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+       unsigned long flags;
+       dma_addr_t alloc_dma;
+       u8 *mem;
+-      int i, reply_sz, req_sz, sz, total_size, num_chain, total_num_chain;
+-        int scale, scale1, num_sge, numSGE, maxSGEs, SGE_size;
+-      int max_sg_tablesize;
++      int i, reply_sz, sz, total_size, num_chain, total_num_chain;
++      int scale, scale1, num_sge, numSGE, maxSGEs, SGE_size;
+       /*  Prime reply FIFO...  */
+@@ -4073,13 +3832,12 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+                       " numSGE=%d MaxChainDepth=%d maxSGEs=%d mpt_sg_tablesize=%d\n",
+                       ioc->name, ioc->req_sz, SGE_size, scale, num_sge, numSGE, 
+                       ioc->facts.MaxChainDepth, maxSGEs, mpt_sg_tablesize));
+-              max_sg_tablesize = mpt_sg_tablesize;
+-              if (max_sg_tablesize > maxSGEs) {
+-                      max_sg_tablesize = maxSGEs;
+-                      dinitprintk((KERN_INFO MYNAM ": %s max_sg_tablesize=%d now\n",
+-                              ioc->name, max_sg_tablesize));
+-              } else if (max_sg_tablesize < maxSGEs) {
+-                      numSGE = max_sg_tablesize - num_sge;
++              if (mpt_sg_tablesize > maxSGEs) {
++                      mpt_sg_tablesize = maxSGEs;
++                      dinitprintk((KERN_INFO MYNAM ": %s mpt_sg_tablesize=%d now\n",
++                              ioc->name, mpt_sg_tablesize));
++              } else if (mpt_sg_tablesize < maxSGEs) {
++                      numSGE = mpt_sg_tablesize - num_sge;
+                       dinitprintk((KERN_INFO MYNAM ": %s numSGE=%d now\n",
+                               ioc->name, numSGE));
+               }
+@@ -4099,12 +3857,11 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+               numSGE = scale1 * (total_num_chain-1);
+               maxSGEs = num_sge + numSGE;
+-              if (max_sg_tablesize > maxSGEs) {
+-                      max_sg_tablesize = maxSGEs;
+-                      dinitprintk((KERN_INFO MYNAM ": %s max_sg_tablesize=%d now, maxSGEs=%d numSGE=%d\n",
+-                              ioc->name, max_sg_tablesize, maxSGEs, numSGE));
++              if (mpt_sg_tablesize > maxSGEs) {
++                      mpt_sg_tablesize = maxSGEs;
++                      dinitprintk((KERN_INFO MYNAM ": %s mpt_sg_tablesize=%d now, maxSGEs=%d numSGE=%d\n",
++                              ioc->name, mpt_sg_tablesize, maxSGEs, numSGE));
+               }
+-              ioc->sg_tablesize = max_sg_tablesize;
+               dinitprintk((KERN_INFO MYNAM ": %s req_depth=%d max num_chain=%d mpt_chain_alloc_percent=%d total_num_chain=%d\n",
+                       ioc->name, ioc->req_depth, num_chain, mpt_chain_alloc_percent, total_num_chain));
+@@ -4116,17 +3873,14 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+               dinitprintk((KERN_INFO MYNAM ": %s Total ReplyBuffer sz=%d[%x] bytes\n",
+                               ioc->name, reply_sz, reply_sz));
+-                req_sz = ioc->req_sz;
+-                sz = (req_sz * ioc->req_depth);
+-
+-      dinitprintk((KERN_INFO MYNAM ": %s RequestBuffer sz=%d bytes, RequestDepth=%d\n",
+-                              ioc->name, req_sz, ioc->req_depth));
+-
++              sz = (ioc->req_sz * ioc->req_depth);
++              dinitprintk((KERN_INFO MYNAM ": %s RequestBuffer sz=%d bytes, RequestDepth=%d\n",
++                              ioc->name, ioc->req_sz, ioc->req_depth));
+               dinitprintk((KERN_INFO MYNAM ": %s Total RequestBuffer sz=%d[%x] bytes\n",
+                               ioc->name, sz, sz));
+               total_size += sz;
+-              sz = total_num_chain *req_sz; /* chain buffer pool size */
++              sz = total_num_chain * ioc->req_sz; /* chain buffer pool size */
+               dinitprintk((KERN_INFO MYNAM ": %s Total ChainBuffer sz=%d[%x] bytes total_num_chain=%d\n",
+                               ioc->name, sz, sz, total_num_chain));
+@@ -4182,14 +3936,14 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+ #endif
+               for (i = 0; i < ioc->req_depth; i++) {
+-                      alloc_dma += req_sz;
+-                      mem += req_sz;
++                      alloc_dma += ioc->req_sz;
++                      mem += ioc->req_sz;
+               }
+               ioc->ChainBuffer = mem;
+               ioc->ChainBufferDMA = alloc_dma;
+-              dinitprintk((KERN_INFO MYNAM ": %s ChainBuffers @ %p(%p)\n",
++              dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
+                       ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
+               /* Initialize the free chain Q.
+@@ -4197,6 +3951,10 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+               INIT_LIST_HEAD(&ioc->FreeChainQ);
++              /* initialize the SAS device list */
++
++              INIT_LIST_HEAD(&ioc->sasDeviceList);
++
+               /* Post the chain buffers to the FreeChainQ.
+               */
+               mem = (u8 *)ioc->ChainBuffer;
+@@ -4205,7 +3963,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+                       list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
+ //                    dinitprintk((MYIOC_s_INFO_FMT "Adding %p to FreeChainQ at %d\n",
+  //                           ioc->name, mf, i));
+-                      mem += req_sz;
++                      mem += ioc->req_sz;
+               }
+               /* Initialize Request frames linked list
+@@ -4220,7 +3978,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
+                       /*  Queue REQUESTs *internally*!  */
+                       list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
+-                      mem += req_sz;
++                      mem += ioc->req_sz;
+               }
+               spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+@@ -4293,7 +4051,8 @@ out_fail:
+  *
+  *    Returns 0 for success, non-zero for failure.
+  */
+-int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
++static int
++mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
+               int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
+ {
+       MPIDefaultReply_t *mptReply;
+@@ -4412,7 +4171,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int
+                       intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+                       if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
+                               break;
+-                      msleep_interruptible(10);
++                      msleep_interruptible(1);
+                       count++;
+               }
+       } else {
+@@ -4420,7 +4179,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int
+                       intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+                       if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
+                               break;
+-                          udelay(1000);
++                      MPT_MDELAY(1);
+                       count++;
+               }
+       }
+@@ -4461,7 +4220,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
+                       intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+                       if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
+                               break;
+-                      msleep_interruptible(10);
++                      msleep_interruptible(1);
+                       count++;
+               }
+       } else {
+@@ -4469,7 +4228,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
+                       intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+                       if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
+                               break;
+-                          udelay(1000);
++                      MPT_MDELAY(1);
+                       count++;
+               }
+       }
+@@ -4944,40 +4703,481 @@ GetManufPage0_exit:
+       return rc;
+ }
++
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+- *    mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
++ *    mpt_sas_get_info - Fetch Hw Max and Min Link Rates.  These values
++ *               get overwritten, so must be saved at init time.
+  *    @ioc: Pointer to MPT_ADAPTER structure
+- *    @sas_address: 64bit SAS Address for operation.
+- *    @target_id: specified target for operation
+- *    @bus: specified bus for operation
+- *    @persist_opcode: see below
+- *
+- *    MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
+- *            devices not currently present.
+- *    MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
+- *
+- *    NOTE: Don't use not this function during interrupt time.
++ *    @numPorts: number of ports for this IOC
+  *
+- *    Returns: 0 for success, non-zero error
++ *    Return: 0 for success
++ *    -ENOMEM if no memory available
++ *            -EPERM if not allowed due to ISR context
++ *            -EAGAIN if no msg frames currently available
++ *            -EFAULT for non-successful reply or no reply (timeout)
+  */
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ int
+-mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
++mpt_sas_get_info(MPT_ADAPTER *ioc)
+ {
+-      SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
+-      SasIoUnitControlReply_t         *sasIoUnitCntrReply;
+-      MPT_FRAME_HDR                   *mf = NULL;
+-      MPIHeader_t                     *mpi_hdr;
++      ConfigExtendedPageHeader_t hdr;
++      CONFIGPARMS             cfg;
++      SasIOUnitPage0_t        *sasIoUnitPg0=NULL;
++      dma_addr_t              sasIoUnitPg0_dma;
++      SasPhyPage0_t           *sasPhyPg0=NULL;
++      dma_addr_t              sasPhyPg0_dma;
++      SasDevicePage0_t        *sasDevicePg0=NULL;
++      dma_addr_t              sasDevicePg0_dma;
++      sas_device_info_t       *sasDevice;
++      u32                     devHandle;
++      int                     sasIoUnitPg0_data_sz=0;
++      int                     sasPhyPg0_data_sz=0;
++      int                     sasDevicePg0_data_sz=0;
++      int                     sz;
++      int                     rc;
++      int                     ii;
++      int                     phyCounter;
++      u8                      *mem;
++      u64                     SASAddress64;
++      char                    *ds = NULL;
++      /* Issue a config request to get the number of phys
++       */
++      ioc->sasPhyInfo=NULL;
+-      /* insure garbage is not sent to fw */
+-      switch(persist_opcode) {
++      hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 0;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+-      case MPI_SAS_OP_CLEAR_NOT_PRESENT:
+-      case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
+-              break;
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.physAddr = -1;
++      cfg.pageAddr = 0;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = 10;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              goto mpt_sas_get_info_exit;
++      }
++
++      if (hdr.ExtPageLength == 0) {
++              rc = -EFAULT;
++              goto mpt_sas_get_info_exit;
++      }
++
++      sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
++      sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
++          sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
++      if (!sasIoUnitPg0) {
++              rc = -ENOMEM;
++              goto mpt_sas_get_info_exit;
++      }
++
++      memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
++      cfg.physAddr = sasIoUnitPg0_dma;
++      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++      if ((rc = mpt_config(ioc, &cfg)) != 0) {
++              goto mpt_sas_get_info_exit;
++      }
++
++      /* save the data */
++      ioc->numPhys = sasIoUnitPg0->NumPhys;
++
++      dsasprintk((MYIOC_s_INFO_FMT "Number of PHYS=%d\n",
++          ioc->name, sasIoUnitPg0->NumPhys));
++
++      sz = ioc->numPhys * sizeof (sas_phy_info_t);
++
++      if ((mem = kmalloc(sz, GFP_ATOMIC)) == NULL) {
++              rc = -ENOMEM;
++              goto mpt_sas_get_info_exit;
++      }
++
++      memset(mem, 0, sz);
++      ioc->alloc_total += sz;
++      ioc->sasPhyInfo = (sas_phy_info_t *) mem;
++
++      /* Issue a config request to get phy information. */
++      hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
++      hdr.ExtPageLength = 0;
++      hdr.PageNumber = 0;
++      hdr.Reserved1 = 0;
++      hdr.Reserved2 = 0;
++      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
++
++      cfg.cfghdr.ehdr = &hdr;
++      cfg.dir = 0;    /* read */
++      cfg.timeout = 10;
++
++      /* Fill in information for each phy. */
++      for (ii = 0; ii < ioc->numPhys; ii++) {
++
++              /* Get Phy Pg 0 for each Phy. */
++              cfg.pageAddr = ii;
++              cfg.physAddr = -1;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++
++              if ((rc = mpt_config(ioc, &cfg)) != 0) {
++                      goto mpt_sas_get_info_exit;
++              }
++
++              if (hdr.ExtPageLength == 0) {
++                      rc = -EFAULT;
++                      goto mpt_sas_get_info_exit;
++              }
++
++              sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
++              sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(
++                  ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma);
++              if (!sasPhyPg0) {
++                      rc = -ENOMEM;
++                      goto mpt_sas_get_info_exit;
++              }
++
++              memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
++              cfg.physAddr = sasPhyPg0_dma;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++
++              /* Save HwLinkRate.
++               * It may be modified accidently via FW
++               */
++              if ((rc = mpt_config(ioc, &cfg)) != 0) {
++                      goto mpt_sas_get_info_exit;
++              }
++
++              ioc->sasPhyInfo[ii].hwLinkRate = sasPhyPg0->HwLinkRate;
++              ioc->sasPhyInfo[ii].phyId = ii;
++              ioc->sasPhyInfo[ii].port = sasIoUnitPg0->PhyData[ii].Port;
++              ioc->sasPhyInfo[ii].ControllerDevHandle =
++                  le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle);
++              ioc->sasPhyInfo[ii].PortFlags =
++                  sasIoUnitPg0->PhyData[ii].PortFlags;
++              ioc->sasPhyInfo[ii].PhyFlags =
++                  sasIoUnitPg0->PhyData[ii].PhyFlags;
++              ioc->sasPhyInfo[ii].NegotiatedLinkRate =
++                  sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate;
++              ioc->sasPhyInfo[ii].ControllerPhyDeviceInfo =
++                  le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo);
++
++              memcpy(&SASAddress64,&sasPhyPg0->SASAddress,sizeof(sasPhyPg0->SASAddress));
++              le64_to_cpus(&SASAddress64);
++              if (SASAddress64) {
++                      dsasprintk(("---- SAS PHY PAGE 0 ------------\n"));
++                      dsasprintk(("Handle=0x%X\n",
++                          le16_to_cpu(sasPhyPg0->AttachedDevHandle)));
++                      dsasprintk(("SAS Address=0x%llX\n",SASAddress64));
++                      dsasprintk(("Attached PHY Identifier=0x%X\n",
++                          sasPhyPg0->AttachedPhyIdentifier));
++                      dsasprintk(("Attached Device Info=0x%X\n",
++                          le32_to_cpu(sasPhyPg0->AttachedDeviceInfo)));
++                      dsasprintk(("Programmed Link Rate=0x%X\n",
++                          sasPhyPg0->ProgrammedLinkRate));
++                      dsasprintk(("Hardware Link Rate=0x%X\n",
++                          ioc->sasPhyInfo[ii].hwLinkRate));
++                      dsasprintk(("Change Count=0x%X\n",
++                          sasPhyPg0->ChangeCount));
++                      dsasprintk(("PHY Info=0x%X\n",
++                          le32_to_cpu(sasPhyPg0->PhyInfo)));
++                      dsasprintk(("\n"));
++              }
++
++              pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++                  (u8 *) sasPhyPg0, sasPhyPg0_dma);
++
++              sasPhyPg0=NULL;
++      }
++
++
++      /* Get all Device info and store in linked list. */
++      devHandle = 0xFFFF;
++      phyCounter=0;
++      while(1) {
++              /* Get SAS device page 0 */
++
++              hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
++              hdr.ExtPageLength = 0;
++              hdr.PageNumber = 0;
++              hdr.Reserved1 = 0;
++              hdr.Reserved2 = 0;
++              hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
++              hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
++
++              cfg.cfghdr.ehdr = &hdr;
++              cfg.physAddr = -1;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
++              cfg.dir = 0;    /* read */
++              cfg.timeout = 10;
++
++              if ((rc = mpt_config(ioc, &cfg)) != 0) {
++                      goto mpt_sas_get_info_exit;
++              }
++
++              if (hdr.ExtPageLength == 0) {
++                      rc = -EFAULT;
++                      goto mpt_sas_get_info_exit;
++              }
++
++              sasDevicePg0_data_sz = hdr.ExtPageLength * 4;
++              sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent(
++                  ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma);
++              if (!sasDevicePg0) {
++                      rc = -ENOMEM;
++                      goto mpt_sas_get_info_exit;
++              }
++
++              memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz);
++              cfg.physAddr = sasDevicePg0_dma;
++              cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
++              cfg.pageAddr = devHandle;
++
++              if ((rc = mpt_config(ioc, &cfg)) != 0) {
++
++              /*
++               * break from the while loop when this fails
++               * which means we have discovered all devices
++               */
++                      rc=0;
++                      goto mpt_sas_get_info_exit;
++              }
++
++              dsasprintk(("---- SAS DEVICE PAGE 0 ---------\n"));
++              dsasprintk(("Handle=0x%X\n",le16_to_cpu(sasDevicePg0->DevHandle)));
++              dsasprintk(("Enclosure Handle=0x%X\n",le16_to_cpu(sasDevicePg0->EnclosureHandle)));
++              dsasprintk(("Slot=0x%X\n",le16_to_cpu(sasDevicePg0->Slot)));
++              memcpy(&SASAddress64,&sasDevicePg0->SASAddress,sizeof(sasDevicePg0->SASAddress));
++              le64_to_cpus(&SASAddress64);
++              dsasprintk(("SAS Address=0x%llX\n",SASAddress64));
++              dsasprintk(("Target ID=0x%X\n",sasDevicePg0->TargetID));
++              dsasprintk(("Bus=0x%X\n",sasDevicePg0->Bus));
++              dsasprintk(("PhyNum=0x%X\n",sasDevicePg0->PhyNum));
++              dsasprintk(("AccessStatus=0x%X\n",le16_to_cpu(sasDevicePg0->AccessStatus)));
++              dsasprintk(("Device Info=0x%X\n",le32_to_cpu(sasDevicePg0->DeviceInfo)));
++              dsasprintk(("Flags=0x%X\n",le16_to_cpu(sasDevicePg0->Flags)));
++              dsasprintk(("Physical Port=0x%X\n",sasDevicePg0->PhysicalPort));
++              dsasprintk(("\n"));
++
++              if(phyCounter < ioc->numPhys) {
++                      ioc->sasPhyInfo[phyCounter].SASAddress = SASAddress64;
++                      ioc->sasPhyInfo[phyCounter].devHandle =
++                              le16_to_cpu(sasDevicePg0->DevHandle);
++                      phyCounter++;
++              }else {
++                      if (le32_to_cpu(sasDevicePg0->DeviceInfo) &
++                          (MPI_SAS_DEVICE_INFO_SSP_TARGET |
++                           MPI_SAS_DEVICE_INFO_STP_TARGET |
++                           MPI_SAS_DEVICE_INFO_SATA_DEVICE )) {
++
++                              if ((sasDevice = kmalloc(sizeof (sas_device_info_t),
++                                  GFP_ATOMIC)) == NULL) {
++                                      rc = -ENOMEM;
++                                      goto mpt_sas_get_info_exit;
++                              }
++
++                              memset(sasDevice, 0, sizeof (sas_device_info_t));
++                              ioc->alloc_total += sizeof (sas_device_info_t);
++                              list_add_tail(&sasDevice->list, &ioc->sasDeviceList);
++                              sasDevice->SASAddress = SASAddress64;
++                              sasDevice->TargetId = sasDevicePg0->TargetID;
++                              sasDevice->Bus = sasDevicePg0->Bus;
++                              sasDevice->DeviceInfo =
++                                le32_to_cpu(sasDevicePg0->DeviceInfo);
++                              sasDevice->DevHandle =
++                                 le16_to_cpu(sasDevicePg0->DevHandle);
++                              sasDevice->Flags =
++                                  le16_to_cpu(sasDevicePg0->Flags);
++                              sasDevice->PhyNum = sasDevicePg0->PhyNum;
++                              sasDevice->PhysicalPort =
++                                  sasDevicePg0->PhysicalPort;
++                              if(sasDevice->DeviceInfo &
++                                  MPI_SAS_DEVICE_INFO_SSP_TARGET)
++                                      ds = "sas";
++                              if(sasDevice->DeviceInfo &
++                                  MPI_SAS_DEVICE_INFO_STP_TARGET)
++                                      ds = "stp";
++                              if(sasDevice->DeviceInfo &
++                                  MPI_SAS_DEVICE_INFO_SATA_DEVICE)
++                                      ds = "sata";
++                              dsasprintk(( 
++                                      "Inserting %s device, channel %d, id %d, phy %d\n\n",
++                                      ds,sasDevice->Bus,
++                                      sasDevice->TargetId,
++                                      sasDevicePg0->PhyNum));
++                      }
++              }
++
++              devHandle = (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE
++                      << MPI_SAS_DEVICE_PGAD_FORM_SHIFT) |
++                      le16_to_cpu(sasDevicePg0->DevHandle);
++
++              pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
++                          (u8 *) sasDevicePg0, sasDevicePg0_dma);
++
++              sasDevicePg0=NULL;
++
++      };
++
++mpt_sas_get_info_exit:
++
++
++      if (sasPhyPg0)
++              pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
++                  (u8 *) sasPhyPg0, sasPhyPg0_dma);
++
++      if (sasIoUnitPg0)
++              pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
++                  (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
++
++      if (sasDevicePg0)
++              pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
++                          (u8 *) sasDevicePg0, sasDevicePg0_dma);
++
++      return rc;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++
++static void
++mptbase_sas_process_event_data(MPT_ADAPTER *ioc,
++    MpiEventDataSasDeviceStatusChange_t * pSasEventData)
++{
++      sas_device_info_t       *sasDevice;
++      int                     ii;
++      char                    *ds=NULL;
++
++      switch(pSasEventData->ReasonCode) {
++      case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
++
++              // sanity check so we are not adding a target that is already in the list.
++              list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++                      if (pSasEventData->TargetID ==
++                          sasDevice->TargetId)
++                              return;
++                              break; 
++              }
++
++              if ((le32_to_cpu(pSasEventData->DeviceInfo) &
++                  (MPI_SAS_DEVICE_INFO_SSP_TARGET |
++                   MPI_SAS_DEVICE_INFO_STP_TARGET |
++                   MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) {
++                      break;
++              }
++
++              if ((sasDevice = kmalloc(sizeof (sas_device_info_t),
++                  GFP_ATOMIC)) == NULL) {
++                      break;
++              }
++
++              memset(sasDevice, 0, sizeof (sas_device_info_t));
++              list_add_tail(&sasDevice->list, &ioc->sasDeviceList);
++              ioc->alloc_total += sizeof (sas_device_info_t);
++
++              memcpy(&sasDevice->SASAddress,&pSasEventData->SASAddress,sizeof(u64));
++              le64_to_cpus(&sasDevice->SASAddress);
++              sasDevice->TargetId = pSasEventData->TargetID;
++              sasDevice->Bus = pSasEventData->Bus;
++              sasDevice->DeviceInfo =
++                  le32_to_cpu(pSasEventData->DeviceInfo);
++              sasDevice->DevHandle =
++                  le16_to_cpu(pSasEventData->DevHandle);
++              sasDevice->PhyNum = pSasEventData->PhyNum;
++              pSasEventData->ParentDevHandle =
++                  le16_to_cpu(pSasEventData->ParentDevHandle);
++
++              for(ii=0;ii<ioc->numPhys;ii++) {
++                      if(pSasEventData->ParentDevHandle ==
++                          ioc->sasPhyInfo[ii].ControllerDevHandle) {
++                              sasDevice->PhysicalPort =
++                                  ioc->sasPhyInfo[ii].port;
++                      }
++              }
++
++              if(sasDevice->DeviceInfo &
++                  MPI_SAS_DEVICE_INFO_SSP_TARGET)
++                      ds = "sas";
++              if(sasDevice->DeviceInfo &
++                  MPI_SAS_DEVICE_INFO_STP_TARGET)
++                      ds = "stp";
++              if(sasDevice->DeviceInfo &
++                  MPI_SAS_DEVICE_INFO_SATA_DEVICE)
++                      ds = "sata";
++              dsasprintk(( 
++                      "Inserting %s device, channel %d, id %d, phy %d\n\n",
++                      ds,sasDevice->Bus,
++                      sasDevice->TargetId,
++                      sasDevice->PhyNum));
++              dsasprintk(("SAS Address=0x%llX\n",sasDevice->SASAddress));
++              dsasprintk(("Device Info=0x%X\n",sasDevice->DeviceInfo));
++              dsasprintk(("Physical Port=0x%X\n",sasDevice->PhysicalPort));
++              dsasprintk(("\n"));
++
++              break;
++
++      case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
++
++              list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) {
++
++                      if (le16_to_cpu(pSasEventData->DevHandle) ==
++                          sasDevice->DevHandle) {
++
++                              dsasprintk(("Removing device from link list!!!\n\n"));
++                              list_del(&sasDevice->list);
++                              kfree(sasDevice);
++                              ioc->alloc_total -= sizeof (sas_device_info_t);
++                              break;
++                      }
++              }
++              break;
++
++      case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
++      case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
++      case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
++      default:
++              break;
++      }
++
++
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*
++ *    mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
++ *    @ioc: Pointer to MPT_ADAPTER structure
++ *    @sas_address: 64bit SAS Address for operation.
++ *    @target_id: specified target for operation
++ *    @bus: specified bus for operation
++ *    @persist_opcode: see below
++ *
++ *    MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
++ *            devices not currently present.
++ *    MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
++ *
++ *    NOTE: Don't use not this function during interrupt time.
++ *
++ *    Returns: 0 for success, non-zero error
++ */
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++int
++mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
++{
++      SasIoUnitControlRequest_t       *sasIoUnitCntrReq;
++      SasIoUnitControlReply_t         *sasIoUnitCntrReply;
++      MPT_FRAME_HDR                   *mf = NULL;
++      MPIHeader_t                     *mpi_hdr;
++
++
++      /* insure garbage is not sent to fw */
++      switch(persist_opcode) {
++
++      case MPI_SAS_OP_CLEAR_NOT_PRESENT:
++      case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
++              break;
+       default:
+               return -1;
+@@ -4992,7 +5192,7 @@ mptbase_sas_persist_operation(MPT_ADAPTE
+               dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+                   ioc->name,__FUNCTION__));
+               return -1;
+-        }
++      }
+       mpi_hdr = (MPIHeader_t *) mf;
+       sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+@@ -5303,7 +5503,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
+                               if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
+                                       ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
+-                                      ddvprintk((KERN_INFO MYNAM ": %s noQas due to Capabilities=%x\n",
++                                      ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
+                                               ioc->name, pPP0->Capabilities));
+                               }
+                               ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
+@@ -5452,188 +5652,6 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTE
+       return 0;
+ }
+-/**
+- *    mpt_raid_phys_disk_pg0 - returns phys disk page zero
+- *    @ioc: Pointer to a Adapter Structure
+- *    @phys_disk_num: io unit unique phys disk num generated by the ioc
+- *    @phys_disk: requested payload data returned
+- *
+- *    Return:
+- *    0 on success
+- *    -EFAULT if read of config page header fails or data pointer not NULL
+- *    -ENOMEM if pci_alloc failed
+- **/
+-int
+-mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
+-{
+-      CONFIGPARMS                     cfg;
+-      ConfigPageHeader_t              hdr;
+-      dma_addr_t                      dma_handle;
+-      pRaidPhysDiskPage0_t            buffer = NULL;
+-      int                             rc;
+-
+-      memset(&cfg, 0 , sizeof(CONFIGPARMS));
+-      memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+-
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+-      cfg.cfghdr.hdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              rc = -EFAULT;
+-              goto out;
+-      }
+-
+-      if (!hdr.PageLength) {
+-              rc = -EFAULT;
+-              goto out;
+-      }
+-
+-      buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+-          &dma_handle);
+-
+-      if (!buffer) {
+-              rc = -ENOMEM;
+-              goto out;
+-      }
+-
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-      cfg.pageAddr = phys_disk_num;
+-
+-      if (mpt_config(ioc, &cfg) != 0) {
+-              rc = -EFAULT;
+-              goto out;
+-      }
+-
+-      rc = 0;
+-      memcpy(phys_disk, buffer, sizeof(*buffer));
+-      phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
+-
+- out:
+-
+-      if (buffer)
+-              pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+-                  dma_handle);
+-
+-      return rc;
+-}
+-
+-/**
+- * mpt_inactive_raid_list_free
+- *
+- * This clears this link list.
+- *
+- * @ioc - pointer to per adapter structure
+- *
+- **/
+-static void
+-mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
+-{
+-      struct inactive_raid_component_info *component_info, *pNext;
+-
+-      if (list_empty(&ioc->raid_data.inactive_list))
+-              return;
+-
+-      down(&ioc->raid_data.inactive_list_mutex);
+-      list_for_each_entry_safe(component_info, pNext,
+-          &ioc->raid_data.inactive_list, list) {
+-              list_del(&component_info->list);
+-              kfree(component_info);
+-      }
+-      up(&ioc->raid_data.inactive_list_mutex);
+-}
+-
+-/**
+- * mpt_inactive_raid_volumes
+- *
+- * This sets up link list of phy_disk_nums for devices belonging in an inactive volume
+- *
+- * @ioc - pointer to per adapter structure
+- * @channel - volume channel
+- * @id - volume target id
+- *
+- *
+- **/
+-static void
+-mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-      CONFIGPARMS                     cfg;
+-      ConfigPageHeader_t              hdr;
+-      dma_addr_t                      dma_handle;
+-      pRaidVolumePage0_t              buffer = NULL;
+-      int                             i;
+-      RaidPhysDiskPage0_t             phys_disk;
+-      struct inactive_raid_component_info *component_info;
+-      int                             handle_inactive_volumes;
+-
+-      memset(&cfg, 0 , sizeof(CONFIGPARMS));
+-      memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+-      cfg.pageAddr = (channel << 8) + id;
+-      cfg.cfghdr.hdr = &hdr;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-
+-      if (mpt_config(ioc, &cfg) != 0)
+-              goto out;
+-
+-      if (!hdr.PageLength)
+-              goto out;
+-
+-      buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+-          &dma_handle);
+-
+-      if (!buffer)
+-              goto out;
+-
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if (mpt_config(ioc, &cfg) != 0)
+-              goto out;
+-
+-      if (!buffer->NumPhysDisks)
+-              goto out;
+-
+-      handle_inactive_volumes =
+-         (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
+-         (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
+-          buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
+-          buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
+-
+-      if (!handle_inactive_volumes)
+-              goto out;
+-
+-      down(&ioc->raid_data.inactive_list_mutex);
+-      for (i = 0; i < buffer->NumPhysDisks; i++) {
+-              if(mpt_raid_phys_disk_pg0(ioc,
+-                  buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+-                      continue;
+-
+-              if ((component_info = kmalloc(sizeof (*component_info),
+-               GFP_KERNEL)) == NULL)
+-                      continue;
+-
+-              component_info->volumeID = id;
+-              component_info->volumeBus = channel;
+-              component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
+-              component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
+-              component_info->d.PhysDiskID = phys_disk.PhysDiskID;
+-              component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
+-
+-              list_add_tail(&component_info->list,
+-                  &ioc->raid_data.inactive_list);
+-      }
+-      up(&ioc->raid_data.inactive_list_mutex);
+-
+- out:
+-      if (buffer)
+-              pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+-                  dma_handle);
+-}
+-
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+  *    mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
+@@ -5657,16 +5675,8 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
+       int                      jj;
+       int                      rc = 0;
+       int                      iocpage2sz;
+-
+-      if (!ioc->ir_firmware)
+-              return 0;
+-
+-      /* Free the old page
+-       */
+-      kfree(ioc->raid_data.pIocPg2);
+-      ioc->raid_data.pIocPg2 = NULL;
+-      mpt_inactive_raid_list_free(ioc);
+-      ioc->raid_data.isRaid = 0;
++      u8                       nVols, nPhys;
++      u8                       vid, vbus, vioc;
+       /* Read IOCP2 header then the page.
+        */
+@@ -5696,35 +5706,53 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
+       if (mpt_config(ioc, &cfg) != 0)
+               goto done_and_free;
+-      mem = kmalloc(iocpage2sz, GFP_ATOMIC);
+-      if (!mem)
+-              goto done_and_free;
+-
++      if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
++              mem = kmalloc(iocpage2sz, GFP_ATOMIC);
++              if (mem) {
++                      ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
++              } else {
++                      goto done_and_free;
++              }
++      }
+       memcpy(mem, (u8 *)pIoc2, iocpage2sz);
+-      ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
+       /* Identify RAID Volume Id's */
+-      if (pIoc2->NumActiveVolumes) {
+-
+-              pIocRv = pIoc2->RaidVolume;
+-              /*
+-               * WARNING - ioc->raid_data.isRaid
+-               * doesn't consider channels
++      nVols = pIoc2->NumActiveVolumes;
++      if ( nVols == 0) {
++              /* No RAID Volume.
+                */
+-              for (jj = 0; jj < pIoc2->NumActiveVolumes; jj++, pIocRv++) {
+-                      if (pIocRv->VolumeBus)
+-                              continue;
+-                      ioc->raid_data.isRaid |= (1 << pIocRv->VolumeID);
+-                      mpt_inactive_raid_volumes(ioc,
+-                          pIoc2->RaidVolume[jj].VolumeBus,
+-                          pIoc2->RaidVolume[jj].VolumeID);
++              goto done_and_free;
++      } else {
++              /* At least 1 RAID Volume
++               */
++              pIocRv = pIoc2->RaidVolume;
++              ioc->raid_data.isRaid = 0;
++              for (jj = 0; jj < nVols; jj++, pIocRv++) {
++                      vid = pIocRv->VolumeID;
++                      vbus = pIocRv->VolumeBus;
++                      vioc = pIocRv->VolumeIOC;
++
++                      /* find the match
++                       */
++                      if (vbus == 0) {
++                              ioc->raid_data.isRaid |= (1 << vid);
++                      } else {
++                              /* Error! Always bus 0
++                               */
++                      }
+               }
+-                   mpt_read_ioc_pg_3(ioc);
+-                     mpt_read_ioc_pg_6(ioc);
+-        }
++      }
++      /* Identify Hidden Physical Disk Id's */
++      nPhys = pIoc2->NumActivePhysDisks;
++      if (nPhys == 0) {
++              /* No physical disks.
++               */
++      } else {
++              mpt_read_ioc_pg_3(ioc);
++      }
+- done_and_free:
++done_and_free:
+       pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
+       return rc;
+@@ -5845,65 +5873,6 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
+ }
+ static void
+-mpt_read_ioc_pg_6(MPT_ADAPTER *ioc)
+-{
+-      IOCPage6_t              *pIoc6;
+-      u8                      *mem;
+-      CONFIGPARMS              cfg;
+-      ConfigPageHeader_t       header;
+-      dma_addr_t               ioc6_dma;
+-      int                      iocpage6sz = 0;
+-
+-      /* Free the old page
+-       */
+-      if (ioc->raid_data.pIocPg6) {
+-              kfree(ioc->raid_data.pIocPg6);
+-              ioc->raid_data.pIocPg6 = NULL;
+-      }
+-
+-      /* There is at least one physical disk.
+-       * Read and save IOC Page 3
+-       */
+-      header.PageVersion = 0;
+-      header.PageLength = 0;
+-      header.PageNumber = 6;
+-      header.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-      cfg.cfghdr.hdr = &header;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = 0;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;
+-      cfg.timeout = 0;
+-      if (mpt_config(ioc, &cfg) != 0)
+-              return;
+-
+-      if (header.PageLength == 0)
+-              return;
+-
+-      /* Read Header good, alloc memory
+-       */
+-      iocpage6sz = header.PageLength * 4;
+-      pIoc6 = pci_alloc_consistent(ioc->pcidev, iocpage6sz, &ioc6_dma);
+-      if (!pIoc6)
+-              return;
+-
+-      /* Read the Page and save the data
+-       * into malloc'd memory.
+-       */
+-      cfg.physAddr = ioc6_dma;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-      if (mpt_config(ioc, &cfg) == 0) {
+-              mem = kmalloc(iocpage6sz, GFP_ATOMIC);
+-              if (mem) {
+-                      memcpy(mem, (u8 *)pIoc6, iocpage6sz);
+-                      ioc->raid_data.pIocPg6 = (IOCPage6_t *) mem;
+-              }
+-      }
+-
+-      pci_free_consistent(ioc->pcidev, iocpage6sz, pIoc6, ioc6_dma);
+-}
+-
+-static void
+ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
+ {
+       IOCPage1_t              *pIoc1;
+@@ -6007,12 +5976,13 @@ SendEventNotification(MPT_ADAPTER *ioc, 
+                   ioc->name,__FUNCTION__));
+               return 0;
+       }
+-      ioc->evnp = evnp;
+-        memset(evnp, 0, sizeof(*evnp));
++      memset(evnp, 0, sizeof(*evnp));
+       devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
+       evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
++      evnp->ChainOffset = 0;
++      evnp->MsgFlags = 0;
+       evnp->Switch = EvSwitch;
+       mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
+@@ -6037,10 +6007,13 @@ SendEventAck(MPT_ADAPTER *ioc, EventNoti
+               return -1;
+       }
+-      devtprintk((MYIOC_s_INFO__FMT "Sending EventAck\n", ioc->name));
+-        memset(pAck, 0, sizeof(*pAck));
++      devtprintk((MYIOC_s_WARN_FMT "Sending EventAck\n", ioc->name));
+       pAck->Function     = MPI_FUNCTION_EVENT_ACK;
++      pAck->ChainOffset  = 0;
++      pAck->Reserved[0]  = pAck->Reserved[1] = 0;
++      pAck->MsgFlags     = 0;
++      pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
+       pAck->Event        = evnp->Event;
+       pAck->EventContext = evnp->EventContext;
+       DBG_DUMP_EVENT_REQUEST_FRAME(pAck);
+@@ -6080,7 +6053,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
+        */
+       in_isr = in_interrupt();
+       if (in_isr) {
+-              dfailprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
++              dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
+                               ioc->name));
+               return -EPERM;
+       }
+@@ -6607,12 +6580,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
+        * mpt_do_ioc_recovery at any instant in time.
+        */
+       spin_lock_irqsave(&ioc->diagLock, flags);
+-         if (ioc->IOCResetInProgress){
++      if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
+               spin_unlock_irqrestore(&ioc->diagLock, flags);
+-      dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler: IOCResetInProgress!\n",
+-              ioc->name));
+-
+-                return 0;
++              return 0;
++      } else {
++              ioc->diagPending = 1;
+       }
+       spin_unlock_irqrestore(&ioc->diagLock, flags);
+@@ -6633,6 +6605,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
+                               dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
+                                               ioc->name, ii));
+                               r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
++                              if (ioc->alt_ioc) {
++                                      dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
++                                                      ioc->name, ioc->alt_ioc->name, ii));
++                                      r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
++                              }
+                       }
+               }
+       }
+@@ -6642,307 +6619,23 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
+                       rc, ioc->name);
+       }
+       ioc->reload_fw = 0;
++      if (ioc->alt_ioc)
++              ioc->alt_ioc->reload_fw = 0;
+-      if (ioc->alt_ioc) {
+-  dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler alt_ioc: checking IOCResetInProgress=%d\n",
+-                      ioc->alt_ioc->name, ioc->alt_ioc->IOCResetInProgress));
+-      spin_lock_irqsave(&ioc->alt_ioc->diagLock, flags);
+-
+-if (ioc->alt_ioc->IOCResetInProgress) {
+- dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler: alt_ioc IOCResetInProgress!\n", ioc->alt_ioc->name));
+-
+-spin_unlock_irqrestore(&ioc->alt_ioc->diagLock, flags);
+-return 0;
+-}
+-spin_unlock_irqrestore(&ioc->alt_ioc->diagLock, flags);
+-if ((rc = mpt_do_ioc_recovery(ioc->alt_ioc, MPT_HOSTEVENT_IOC_RECOVER,
+-sleepFlag)) != 0) {
+-printk(KERN_WARNING MYNAM ": WARNING - alt_%s mpt_do_ioc_recovery failed rc=%x\n", ioc->name,   rc );
+-     }
+-ioc->alt_ioc->reload_fw = 0;
+-}
+-
++      spin_lock_irqsave(&ioc->diagLock, flags);
++      ioc->diagPending = 0;
++      if (ioc->alt_ioc)
++              ioc->alt_ioc->diagPending = 0;
++      spin_unlock_irqrestore(&ioc->diagLock, flags);
+       dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
+       return rc;
+ }
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*    mpt_writeSDP1  - write SCSI Device Page 1
+- *    @ioc: Pointer to a SCSI Host Adapter Structure
+- *    @portnum: IOC port number
+- *    @id: writeSDP1 for single ID
+- *    @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
+- *
+- *    Return: -EFAULT if read of config page header fails
+- *            or 0 if success.
+- *
+- *    Remark: If a target has been found, the settings from the
+- *            target structure are used, else the device is set
+- *            to async/narrow.
+- *
+- *    Remark: Called during init and after a FW reload.
+- *    Remark: We do not wait for a return, write pages sequentially.
+- */
+-int
+-mpt_writeSDP1(MPT_ADAPTER *ioc, int portnum, int id, int flags)
+-{
+-      Config_t                *pReq;
+-      SCSIDevicePage1_t       *pData;
+-      struct _MPT_DEVICE      *pMptTarget;
+-      VirtDevice              *pTarget;
+-      MPT_FRAME_HDR           *mf;
+-      dma_addr_t               dataDma;
+-      u16                      req_idx;
+-      u32                      frameOffset;
+-      u32                      requested, configuration, flagsLength;
+-      int                      ii, nvram;
+-      int                      loop_id, loop_end;
+-      u8                       width;
+-      u8                       factor;
+-      u8                       offset;
+-      u8                       bus = 0;
+-      u8                       negoFlags;
+-      u8                       maxwidth, maxoffset, maxfactor;
+-
+-      if ((pMptTarget = ioc->Target_List[0]) == NULL)
+-              return 0;
+-
+-      if (ioc->spi_data.sdp1length == 0)
+-              return 0;
+-
+-      if (flags & MPT_SCSICFG_ALL_IDS) {
+-              loop_id = 0;
+-              loop_end = ioc->DevicesPerBus;
+-      } else {
+-              loop_id = id;
+-              loop_end = id+1;
+-      }
+-
+-      for (; loop_id < loop_end; loop_id++) {
+-
+-              if (loop_id == ioc->pfacts[portnum].PortSCSIID)
+-                      continue;
+-
+-
+-              pTarget = pMptTarget->Target[loop_id];
+-
+-              /* Use NVRAM to get adapter and target maximums
+-               * Data over-riden by target structure information, if present
+-               */
+-              maxwidth = ioc->spi_data.maxBusWidth;
+-              maxoffset = ioc->spi_data.maxSyncOffset;
+-              maxfactor = ioc->spi_data.minSyncFactor;
+-              if (ioc->spi_data.nvram && (ioc->spi_data.nvram[loop_id] != MPT_HOST_NVRAM_INVALID)) {
+-                      nvram = ioc->spi_data.nvram[loop_id];
+-
+-                      if (maxwidth)
+-                              maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+-
+-                      if (maxoffset > 0) {
+-                              maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
+-                              if (maxfactor == 0) {
+-                                      /* Key for async */
+-                                      maxfactor = MPT_ASYNC;
+-                                      maxoffset = 0;
+-                              } else if (maxfactor < ioc->spi_data.minSyncFactor) {
+-                                      maxfactor = ioc->spi_data.minSyncFactor;
+-                              }
+-                      } else
+-                              maxfactor = MPT_ASYNC;
+-              }
+-
+-              /* Set the negotiation flags.
+-               */
+-              negoFlags = ioc->spi_data.noQas;
+-              if (!maxwidth)
+-                      negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+-
+-              if (!maxoffset)
+-                      negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+-
+-              if (flags & MPT_SCSICFG_USE_NVRAM) {
+-                      width = maxwidth;
+-                      factor = maxfactor;
+-                      offset = maxoffset;
+-                      dnegoprintk(("%s: writeSDP1: USE_NVRAM id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-                              ioc->name, loop_id, width, factor, offset, negoFlags));
+-              } else {
+-                      width = 0;
+-                      factor = MPT_ASYNC;
+-                      offset = 0;
+-                      //negoFlags = 0;
+-                      //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
+-                      dnegoprintk(("%s: writeSDP1: !USE_NVRAM: Going Async/Narrow id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-                              ioc->name, loop_id, width, factor, offset, negoFlags));
+-              }
+-
+-              /* If id is not a raid volume, get the updated
+-               * transmission settings from the target structure.
+-               */
+-              if ( pTarget && !pTarget->raidVolume) {
+-                      width = pTarget->maxWidth;
+-                      factor = pTarget->minSyncFactor;
+-                      offset = pTarget->maxOffset;
+-                      negoFlags |= pTarget->negoFlags;
+-                      dnegoprintk(("%s: writeSDP1: NOT RAID id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-                              ioc->name, loop_id, width, factor, offset, negoFlags));
+-              }
+-
+-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+-              /* Force to async and narrow if DV has not been executed
+-               * for this ID
+-               */
+-              if ((ioc->spi_data.dvStatus[loop_id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
+-                      width = 0;
+-                      factor = MPT_ASYNC;
+-                      offset = 0;
+-                      dnegoprintk(("%s: writeSDP1: DV_NOT_DONE: Going Async/Narrow id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-                              ioc->name, loop_id, width, factor, offset, negoFlags));
+-              }
+-#endif
+-
+-              if (flags & MPT_SCSICFG_BLK_NEGO) {
+-                      negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
+-                      dnegoprintk(("%s: writeSDP1: BLK_NEGO id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-                              ioc->name, loop_id, width, factor, offset, negoFlags));
+-              }
+-
+-              mpt_setSDP1parameters(width, factor, offset, negoFlags,
+-                              &requested, &configuration);
+-
+-              /* Get a MF for this command.
+-               */
+-              if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
+-                      dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-                          ioc->name,__FUNCTION__));
+-                      return -EAGAIN;
+-              }
+-
+-              /* Set the request and the data pointers.
+-               * Request takes: 36 bytes (32 bit SGE)
+-               * SCSI Device Page 1 requires 16 bytes
+-               * 40 + 16 <= size of SCSI IO Request = 56 bytes
+-               * and MF size >= 64 bytes.
+-               * Place data at end of MF.
+-               */
+-              pReq = (Config_t *)mf;
+-
+-              req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-              frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
+-
+-              pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
+-              dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
+-
+-              /* Complete the request frame (same for all requests).
+-               */
+-              pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+-              pReq->Reserved = 0;
+-              pReq->ChainOffset = 0;
+-              pReq->Function = MPI_FUNCTION_CONFIG;
+-              pReq->ExtPageLength = 0;
+-              pReq->ExtPageType = 0;
+-              pReq->MsgFlags = 0;
+-              for (ii=0; ii < 8; ii++) {
+-                      pReq->Reserved2[ii] = 0;
+-              }
+-              pReq->Header.PageVersion = ioc->spi_data.sdp1version;
+-              pReq->Header.PageLength = ioc->spi_data.sdp1length;
+-              pReq->Header.PageNumber = 1;
+-              pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+-              pReq->PageAddress = cpu_to_le32(loop_id | (bus << 8 ));
+-
+-              /* Add a SGE to the config request.
+-               */
+-              flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
+-
+-              mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
+-
+-              /* Set up the common data portion
+-               */
+-              pData->Header.PageVersion = pReq->Header.PageVersion;
+-              pData->Header.PageLength = pReq->Header.PageLength;
+-              pData->Header.PageNumber = pReq->Header.PageNumber;
+-              pData->Header.PageType = pReq->Header.PageType;
+-              pData->RequestedParameters = cpu_to_le32(requested);
+-              pData->Reserved = 0;
+-              pData->Configuration = cpu_to_le32(configuration);
+-
+-              if ( pTarget ) {
+-                      if ( requested & MPI_SCSIDEVPAGE1_RP_IU ) {
+-                              pTarget->last_lun = MPT_LAST_LUN;
+-                      } else {
+-                              pTarget->last_lun = MPT_NON_IU_LAST_LUN;
+-                      }
+-                      dsprintk((MYIOC_s_INFO_FMT
+-                              "writeSDP1: last_lun=%d on id=%d\n",
+-                              ioc->name, pTarget->last_lun, loop_id));
+-              }
+-
+-              dnegoprintk((MYIOC_s_INFO_FMT
+-                      "write SDP1: id=%d pgaddr=0x%x requested=%08x configuration=%08x\n",
+-                              ioc->name, loop_id, (loop_id | (bus<<8)),
+-                              requested, configuration));
+-
+-              mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+-      }
+-      return 0;
+-}
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*    mpt_setSDP1parameters  - set SDP1 Requested and Configuration
+- *    fields based on width, factor, offset and flags parameters.
+- *    @width: bus width
+- *    @factor: sync factor
+- *    @offset: sync offset
+- *    @flags: flags to block WDTR or SDTR negotiation
+- *    @requestedPtr: pointer to SDP1 Requested value (updated)
+- *    @configurationPtr: pointer to SDP1 Configuration value (updated)
+- *
+- *    Return: None.
+- *
+- *    Remark: Called by writeSDP1 and _dv_params
+- */
+-void
+-mpt_setSDP1parameters (u8 width, u8 factor, u8 offset, u8 flags, int *requestedPtr, int *configurationPtr)
+-{
+-      u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
+-      u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
+-
+-      *configurationPtr = 0;
+-      *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
+-      *requestedPtr |= (offset << 16) | (factor << 8);
+-
+-      if (width && offset && !nowide && !nosync) {
+-              if (factor < MPT_ULTRA160) {
+-                      *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
+-                      if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
+-                              *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
+-                      if (flags & MPT_TAPE_NEGO_IDP)
+-                              *requestedPtr |= 0x08000000;
+-              } else if (factor < MPT_ULTRA2) {
+-                      *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
+-              }
+-      }
+-
+-      if (nowide)
+-              *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
+-
+-      if (nosync)
+-              *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
+-
+-      return;
+-}
+-
+ # define EVENT_DESCR_STR_SZ           100
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-
+-
+-
+-
+-
+ static void
+ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
+ {
+@@ -6969,6 +6662,9 @@ EventDescriptionStr(u8 event, u32 evData
+               break;
+       case MPI_EVENT_RESCAN:
+               ds = "Bus Rescan Event";
++              /* Ok, do we need to do anything here? As far as
++                 I can tell, this is when a new device gets added
++                 to the loop. */
+               break;
+       case MPI_EVENT_LINK_STATUS_CHANGE:
+               if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
+@@ -6980,9 +6676,9 @@ EventDescriptionStr(u8 event, u32 evData
+               if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
+                       ds = "Loop State(LIP) Change";
+               else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
+-                      ds = "Loop State(LPE) Change";          /* ??? */
++                      ds = "Loop State(LPE) Change";                  /* ??? */
+               else
+-                      ds = "Loop State(LPB) Change";          /* ??? */
++                      ds = "Loop State(LPB) Change";                  /* ??? */
+               break;
+       case MPI_EVENT_LOGOUT:
+               ds = "Logout";
+@@ -6995,6 +6691,9 @@ EventDescriptionStr(u8 event, u32 evData
+               break;
+       case MPI_EVENT_INTEGRATED_RAID:
+       {
++#if defined(CPQ_CIM)
++        ioc->csmi_change_count++;
++#endif
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_RAID_RC_VOLUME_CREATED :
+@@ -7044,65 +6743,36 @@ EventDescriptionStr(u8 event, u32 evData
+               break;
+       case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+       {
+-              u8 id = (u8)(evData0);
+-              u8 channel = (u8)(evData0 >> 8);
++        u8 id = (u8)(evData0);
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: Added: "
+-                          "id=%d channel=%d", id, channel);
++                          "SAS Device Status Change: Added: id=%d", id);
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: Deleted: "
+-                          "id=%d channel=%d", id, channel);
++                          "SAS Device Status Change: Deleted: id=%d", id);
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: SMART Data: "
+-                          "id=%d channel=%d", id, channel);
++                          "SAS Device Status Change: SMART Data: id=%d",
++                          id);
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: No Persistancy: "
+-                          "id=%d channel=%d", id, channel);
+-                      break;
+-              case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: Unsupported Device "
+-                          "Discovered : id=%d channel=%d", id, channel);
+-                      break;
+-              case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: Internal Device "
+-                          "Reset : id=%d channel=%d", id, channel);
+-                      break;
+-              case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: Internal Task "
+-                          "Abort : id=%d channel=%d", id, channel);
+-                      break;
+-              case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: Internal Abort "
+-                          "Task Set : id=%d channel=%d", id, channel);
+-                      break;
+-              case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: Internal Clear "
+-                          "Task Set : id=%d channel=%d", id, channel);
+-                      break;
+-              case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: Internal Query "
+-                          "Task : id=%d channel=%d", id, channel);
++                          "SAS Device Status Change: No Persistancy "
++                          "Added: id=%d", id);
+                       break;
++        case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
++            snprintf(evStr, EVENT_DESCR_STR_SZ,
++                "SAS Device Status Change: Internal Device Reset: "
++                "id=%d", id);
++            break;
+               default:
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS Device Status Change: Unknown: "
+-                          "id=%d channel=%d", id, channel);
+-                      break;
++                          "SAS Device Status Change: Unknown: id=%d", id);
++                      break;          
+               }
+               break;
+       }
+@@ -7205,86 +6875,15 @@ EventDescriptionStr(u8 event, u32 evData
+       }
+       case MPI_EVENT_SAS_DISCOVERY:
+       {
+-              if (evData0)
+-                      ds = "SAS Discovery: Start";
+-              else
+-                      ds = "SAS Discovery: Stop";
++              char buf[40];
++              sprintf(buf,"SAS Discovery: Condition=0x%x:",evData0);
++              ds = buf;
+               break;
+       }
+       case MPI_EVENT_LOG_ENTRY_ADDED:
+               ds = "SAS Log Entry Added";
+               break;
+-      case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
+-      {
+-              u8 phy_num = (u8)(evData0);
+-              u8 port_num = (u8)(evData0 >> 8);
+-              u8 port_width = (u8)(evData0 >> 16);
+-              u8 primative = (u8)(evData0 >> 24);
+-              snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                  "SAS Broadcase Primative: phy=%d port=%d "
+-                  "width=%d primative=0x%02x",
+-                  phy_num, port_num, port_width, primative);
+-              break;
+-      }
+-
+-      case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
+-      {
+-              u8 reason = (u8)(evData0);
+-              u8 port_num = (u8)(evData0 >> 8);
+-              u16 handle = le16_to_cpu(evData0 >> 16);
+-
+-              snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                  "SAS Initiator Device Status Change: reason=0x%02x "
+-                  "port=%d handle=0x%04x",
+-                  reason, port_num, handle);
+-              break;
+-      }
+-
+-      case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
+-      {
+-              u8 max_init = (u8)(evData0);
+-              u8 current_init = (u8)(evData0 >> 8);
+-
+-              snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                  "SAS Initiator Device Table Overflow: max initiators=%02d "
+-                  "current initators=%02d",
+-                  max_init, current_init);
+-              break;
+-      }
+-      case MPI_EVENT_SAS_SMP_ERROR:
+-      {
+-              u8 status = (u8)(evData0);
+-              u8 port_num = (u8)(evData0 >> 8);
+-              u8 result = (u8)(evData0 >> 16);
+-
+-              if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS SMP Error: port=%d result=0x%02x",
+-                          port_num, result);
+-              else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS SMP Error: port=%d : CRC Error",
+-                          port_num);
+-              else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS SMP Error: port=%d : Timeout",
+-                          port_num);
+-              else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS SMP Error: port=%d : No Destination",
+-                          port_num);
+-              else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS SMP Error: port=%d : Bad Destination",
+-                          port_num);
+-              else
+-                      snprintf(evStr, EVENT_DESCR_STR_SZ,
+-                          "SAS SMP Error: port=%d : status=0x%02x",
+-                          port_num, status);
+-              break;
+-      }
+-
+       /*
+        *  MPT base "custom" events may be added here...
+        */
+@@ -7329,20 +6928,24 @@ ProcessEventNotification(MPT_ADAPTER *io
+       }
+       EventDescriptionStr(event, evData0, evStr);
+-      devtprintk((MYIOC_s_WARN_FMT "MPT event:(%02Xh) : %s\n",
+-          ioc->name, event, evStr));
++      devtprintk((MYIOC_s_WARN_FMT "MPT Event=%02Xh (%s) detected!\n",
++                      ioc->name, event, evStr));
++
+ #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
+-       printk(KERN_WARN MYNAM ": Event data:\n" KERN_INFO);
+-       for (ii = 0; ii < evDataLen; ii++)
+-               printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
+-       printk("\n");
++      printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
++      for (ii = 0; ii < evDataLen; ii++)
++              printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
++      printk("\n");
+ #endif
+-
+-       /*
++      /*
+        *  Do general / base driver event processing
+        */
+       switch(event) {
++      case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: /* 0F */
++              mptbase_sas_process_event_data(ioc,
++                  (MpiEventDataSasDeviceStatusChange_t *)pEventReply->Data);
++              break;
+       case MPI_EVENT_EVENT_CHANGE:            /* 0A */
+               if (evDataLen) {
+                       u8 evState = evData0 & 0xFF;
+@@ -7359,11 +6962,6 @@ ProcessEventNotification(MPT_ADAPTER *io
+               mptbase_raid_process_event_data(ioc,
+                   (MpiEventDataRaid_t *)pEventReply->Data);
+               break;
+-case MPI_EVENT_RESCAN:
+-case MPI_EVENT_LINK_STATUS_CHANGE:
+-ioc->FcLinkSpeedCheckNeeded = 1;
+-break;
+-
+       default:
+               break;
+       }
+@@ -7396,10 +6994,9 @@ break;
+        */
+       for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
+               if (MptEvHandlers[ii]) {
+-              devtprintk((MYIOC_s_WARN_FMT "Routing Event to event handler #%d\n",
+-                                 ioc->name, ii));
+-
+-                       r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
++                      devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
++                                      ioc->name, ii));
++                      r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
+                       handlers++;
+               }
+       }
+@@ -7412,7 +7009,7 @@ break;
+               devtprintk((MYIOC_s_WARN_FMT
+                       "EventAck required\n",ioc->name));
+               if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
+-                      devtprintk((MYIOC_s_INFO_FMT "SendEventAck returned %d\n",
++                      devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
+                                       ioc->name, ii));
+               }
+       }
+@@ -7599,14 +7196,20 @@ union loginfo_type {
+       }
+       if (code_desc != NULL)
+-              printk("Originator={%s}, Code={%s},"
++              printk(MYIOC_s_INFO_FMT
++                      "LogInfo(0x%08x): Originator={%s}, Code={%s},"
+                       " SubCode(0x%04x)\n",
++                      ioc->name,
++                      log_info,
+                       originator_str[sas_loginfo.dw.originator],
+                       code_desc,
+                       sas_loginfo.dw.subcode);
+       else
+-              printk("Originator={%s}, Code=(0x%02x),"
++              printk(MYIOC_s_INFO_FMT
++                      "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
+                       " SubCode(0x%04x)\n",
++                      ioc->name,
++                      log_info,
+                       originator_str[sas_loginfo.dw.originator],
+                       sas_loginfo.dw.code,
+                       sas_loginfo.dw.subcode);
+@@ -7625,12 +7228,7 @@ static void
+ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
+ {
+       u32 status = ioc_status & MPI_IOCSTATUS_MASK;
+-      char *desc = NULL;
+-
+-      SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
+-      U8 cdb = pScsiReq->CDB[0];
+-      U8 id = pScsiReq->TargetID;
+-      U8 lun = pScsiReq->LUN[1];
++      char *desc = "";
+       switch (status) {
+       case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
+@@ -7639,8 +7237,6 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io
+       case MPI_IOCSTATUS_BUSY: /* 0x0002 */
+               desc = "Busy";
+-                ddvprintk (("%s IOCSTATUS_BUSY", ioc->name));
+-                DBG_DUMP_RESET_REQUEST_FRAME(ioc, mf)
+               break;
+       case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
+@@ -7692,11 +7288,11 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io
+       case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
+         {
+-#ifdef MPT_DEBUG_REPLY
++              SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
++              U8 cdb = pScsiReq->CDB[0];
+               if (cdb != 0x12) { /* Inquiry is issued for device scanning */
+                       desc = "SCSI Device Not There";
+               }
+-#endif
+               break;
+         }
+@@ -7742,16 +7338,8 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io
+               desc = "Others";
+               break;
+       }
+-      if (desc != NULL) {
+-              U8 function = pScsiReq->Function;
+-              if (function == MPI_FUNCTION_SCSI_IO_REQUEST ||
+-                  function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
+-                      printk(MYIOC_s_WARN_FMT "IOCStatus(0x%04x): %s on CDB=%x id=%d lun=%d\n", ioc->name, status, desc, cdb, id, lun);
+-              } else {
+-                      printk(MYIOC_s_WARN_FMT "IOCStatus(0x%04x): %s on Function=%02x\n", ioc->name, status, desc, function);
+-              }
+-               DBG_DUMP_REPLYS_REQUEST_FRAME(ioc, mf)
+-      }
++      if (desc != "")
++              printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -7770,6 +7358,7 @@ mpt_poll_interrupt(MPT_ADAPTER *ioc)
+       if (intstat & MPI_HIS_REPLY_MESSAGE_INTERRUPT)
+               mpt_interrupt(0, ioc, NULL);
+ }
++
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ EXPORT_SYMBOL(mpt_attach);
+ EXPORT_SYMBOL(mpt_detach);
+@@ -7779,6 +7368,7 @@ EXPORT_SYMBOL(mpt_suspend);
+ #endif
+ EXPORT_SYMBOL(ioc_list);
+ EXPORT_SYMBOL(mpt_can_queue);
++EXPORT_SYMBOL(mpt_sg_tablesize);
+ EXPORT_SYMBOL(mpt_proc_root_dir);
+ EXPORT_SYMBOL(mpt_register);
+ EXPORT_SYMBOL(mpt_deregister);
+@@ -7800,21 +7390,16 @@ EXPORT_SYMBOL(mpt_print_ioc_summary);
+ EXPORT_SYMBOL(mpt_lan_index);
+ EXPORT_SYMBOL(mpt_stm_index);
+ EXPORT_SYMBOL(mpt_HardResetHandler);
+-EXPORT_SYMBOL(mpt_SendIocReset);
+-EXPORT_SYMBOL(mpt_do_ioc_recovery);
+-EXPORT_SYMBOL(mpt_writeSDP1);
+-EXPORT_SYMBOL(mpt_setSDP1parameters);
+ EXPORT_SYMBOL(mpt_config);
+ EXPORT_SYMBOL(mpt_findImVolumes);
+ EXPORT_SYMBOL(mpt_read_ioc_pg_3);
+ EXPORT_SYMBOL(mpt_alloc_fw_memory);
+ EXPORT_SYMBOL(mpt_free_fw_memory);
+ EXPORT_SYMBOL(mptbase_sas_persist_operation);
++EXPORT_SYMBOL(mpt_sas_get_info);
+ EXPORT_SYMBOL_GPL(mpt_poll_interrupt);
+ EXPORT_SYMBOL(mpt_alt_ioc_wait);
+-EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
+-EXPORT_SYMBOL(mpt_enable_deadioc_detect);
+-EXPORT_SYMBOL(mpt_handshake_req_reply_wait);
++
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.h linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.h        2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.h       2007-11-02 09:10:23.000000000 +0100
+@@ -5,8 +5,8 @@
+  *          LSIFC9xx/LSI409xx Fibre Channel
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (    mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptbase.h,v 1.149 2003/05/07 14:08:31 Exp $
+  */
+@@ -78,14 +78,14 @@
+ #endif
+ #ifndef COPYRIGHT
+-#define COPYRIGHT     "Copyright (c) 1999-2007 " MODULEAUTHOR
++#define COPYRIGHT     "Copyright (c) 1999-2006 " MODULEAUTHOR
+ #endif
+-#define MPT_LINUX_VERSION_COMMON      "3.02.99.00rh"
+-#define MPT_LINUX_PACKAGE_NAME                "@(#)mptlinux-3.02.99.00rh"
++#define MPT_LINUX_VERSION_COMMON      "3.02.73rh"
++#define MPT_LINUX_PACKAGE_NAME                "@(#)mptlinux-3.02.73rh"
+ #define MPT_LINUX_MAJOR_VERSION               3
+ #define MPT_LINUX_MINOR_VERSION               02
+-#define MPT_LINUX_BUILD_VERSION               99
++#define MPT_LINUX_BUILD_VERSION               73
+ #define MPT_LINUX_RELEASE_VERSION     00
+ #define WHAT_MAGIC_STRING             "@" "(" "#" ")"
+@@ -96,8 +96,10 @@
+ /*
+  *  Fusion MPT(linux) driver configurable stuff...
+  */
++#define MPT_MAX_ADAPTERS              18
+ #define MPT_MAX_PROTOCOL_DRIVERS      16
+-#define MPT_MAX_BUSES                 8
++#define MPT_MAX_BUS                   1       /* Do not change */
++#define MPT_MAX_FC_DEVICES            255
+ #define MPT_MAX_SCSI_DEVICES          16
+ #define MPT_LAST_LUN                  255
+ #define MPT_NON_IU_LAST_LUN           63
+@@ -137,9 +139,6 @@
+ #define        CAN_SLEEP                      1
+ #define  NO_SLEEP                     0
+-#define MPT_HZ                         1000
+-#define MPT_JIFFY                      100
+-
+ #define MPT_COALESCING_TIMEOUT                0x10
+ /*
+@@ -170,9 +169,7 @@
+ /*
+  * Default MAX_SGE value.  Can be changed by using mptbase sg_count parameter.
+  */
+-#ifndef CONFIG_FUSION_MAX_SGE
+-#define CONFIG_FUSION_MAX_SGE  128
+-#endif
++#define MPT_SCSI_SG_DEPTH     128
+ #ifdef __KERNEL__     /* { */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -218,6 +215,8 @@ typedef union _MPT_FRAME_TRACKER {
+       struct {
+               struct list_head        list;
+               u32                      arg1;
++              u32                      pad;
++              void                    *argp1;
+       } linkage;
+       /*
+        * NOTE: When request frames are free, on the linkage structure
+@@ -277,12 +276,6 @@ typedef struct _MPT_FRAME_HDR {
+       } u;
+ } MPT_FRAME_HDR;
+-typedef struct _MPT_LINKAGE {
+-              struct list_head        list;
+-              MPT_FRAME_HDR           *mf;
+-} MPT_LINKAGE;
+-
+-
+ #define MPT_REQ_MSGFLAGS_DROPME               0x80
+ typedef struct _MPT_SGL_HDR {
+@@ -336,31 +329,15 @@ typedef struct _SYSIF_REGS
+ #define MPT_TARGET_NO_NEGO_QAS                0x04
+ #define MPT_TAPE_NEGO_IDP                     0x08
+-#if defined(CPQ_CIM)
+-struct sas_mapping{
+-      u8                      id;
+-      u8                      channel;
+-};
+-
+-struct sas_device_info {
+-      struct list_head        list;
+-      struct sas_mapping      os;     /* operating system mapping*/
+-      struct sas_mapping      fw;     /* firmware mapping */
+-      u64                     sas_address;
+-      u32                     device_info; /* specific bits for devices */
+-      u8                      is_logical_volume; /* is this logical volume */
+-      u8                      is_cached;      /* cached data for a removed device */
+-};
+-#endif
+-
+ /*
+  *    VirtDevice - FC LUN device or SCSI target device
+  */
+ typedef struct _VirtDevice {
+-        struct _MPT_ADAPTER   *ioc;
++      struct scsi_device      *device;
+       u16                      tflags;
+-      u8                       id;
+-      u8                       bus;
++      u8                       ioc_id;
++      u8                       target_id;
++      u8                       bus_id;
+       u8                       minSyncFactor; /* 0xFF is async */
+       u8                       maxOffset;     /* 0 if async */
+       u8                       maxWidth;      /* 0 if narrow, 1 if wide */
+@@ -385,13 +362,9 @@ typedef struct _VirtDevice {
+       u8                       pad2[4];
+       U64                      WWPN;
+       U64                      WWNN;
+-       struct work_struct        dvTask;
+-       u8                      configured_lun;
++      u8                       configured_lun;
+ } VirtDevice;
+-typedef struct _MPT_DEVICE {
+-      VirtDevice      *Target[0];
+-} MPT_DEVICE;
+ /*
+  *  Fibre Channel (SCSI) target device and associated defines...
+  */
+@@ -440,6 +413,7 @@ do { \
+ #define MPT_IOCTL_STATUS_SENSE_VALID  0x08    /* Sense data is valid */
+ #define MPT_IOCTL_STATUS_COMMAND_GOOD 0x10    /* Command Status GOOD */
+ #define MPT_IOCTL_STATUS_TMTIMER_ACTIVE       0x20    /* The TM timer is running */
++#define MPT_IOCTL_STATUS_TM_FAILED    0x40    /* User TM request failed */
+ #define MPTCTL_RESET_OK                       0x01    /* Issue Bus Reset */
+@@ -448,10 +422,10 @@ typedef struct _MPT_IOCTL {
+       u8                       ReplyFrame[MPT_DEFAULT_FRAME_SIZE];    /* reply frame data */
+       u8                       sense[MPT_SENSE_BUFFER_ALLOC];
+       int                      wait_done;     /* wake-up value for this ioc */
++      u8                       rsvd;
+       u8                       status;        /* current command status */
+       u8                       reset;         /* 1 if bus reset allowed */
+-      u8                       bus;           /* bus */
+-      u8                       id;            /* id for reset */
++      u8                       target;        /* target for reset */
+       struct semaphore         sem_ioc;
+ } MPT_IOCTL;
+@@ -462,7 +436,7 @@ typedef struct _MPT_IOCTL {
+ typedef struct _mpt_ioctl_events {
+       u32     event;          /* Specified by define above */
+       u32     eventContext;   /* Index or counter */
+-      u32     data[2];        /* First 8 bytes of Event Data */
++      int     data[2];        /* First 8 bytes of Event Data */
+ } MPT_IOCTL_EVENTS;
+ /*
+@@ -477,14 +451,14 @@ typedef struct _mpt_ioctl_events {
+                                               /* dvStatus defines: */
+ #define MPT_SCSICFG_NEGOTIATE         0x01    /* Negotiate on next IO */
+ #define MPT_SCSICFG_NEED_DV           0x02    /* Schedule DV */
+-#define MPT_SCSICFG_DV_IN_PROGRESS    0x04    /* DV on this physical id*/
++#define MPT_SCSICFG_DV_PENDING                0x04    /* DV on this physical id pending */
+ #define MPT_SCSICFG_DV_NOT_DONE               0x08    /* DV has not been performed */
+-#define MPT_SCSICFG_PHYSDISK_DV_ONLY  0x10    /* DV only on this PhysDisk*/
+-#define MPT_SCSICFG_BLK_NEGO          0x20    /* WriteSDP1 with WDTR and SDTR disabled*/
+-#define MPT_SCSICFG_RELOAD_IOC_PG3    0x40    /* IOC Pg 3 data is obsolete */
++#define MPT_SCSICFG_BLK_NEGO          0x10    /* WriteSDP1 with WDTR and SDTR disabled */
++#define MPT_SCSICFG_RELOAD_IOC_PG3    0x20    /* IOC Pg 3 data is obsolete */
+                                               /* Args passed to writeSDP1: */
+ #define MPT_SCSICFG_USE_NVRAM         0x01    /* WriteSDP1 using NVRAM */
+ #define MPT_SCSICFG_ALL_IDS           0x02    /* WriteSDP1 to all IDS */
++/* #define MPT_SCSICFG_BLK_NEGO               0x10       WriteSDP1 with WDTR and SDTR disabled */
+ typedef       struct _SpiCfgData {
+       u32              PortFlags;
+@@ -520,36 +494,48 @@ typedef  struct _SasCfgData {
+                                                * automatic clearing.
+                                                */
+       u8              mpt_sas_hot_plug_enable;  /* disables hot swap device remove support */
+-    ManufacturingPage7_t    *pManufPg7; /* Connector Info on SAS controllers */
+ }SasCfgData;
+-/*
+- * Inactive volume link list of raid component data
+- * @inactive_list
+- */
+-struct inactive_raid_component_info {
+-      struct   list_head list;
+-      u8               volumeID;              /* volume target id */
+-      u8               volumeBus;             /* volume channel */
+-      IOC_3_PHYS_DISK  d;                     /* phys disk info */
+-};
+-
+ typedef       struct _RaidCfgData {
+       IOCPage2_t      *pIocPg2;               /* table of Raid Volumes */
+       IOCPage3_t      *pIocPg3;               /* table of physical disks */
+-      IOCPage6_t      *pIocPg6;       /* table of IR static data */
+-      int              isRaid;                    /* bit field, 1 if RAID */
+-      struct semaphore        inactive_list_mutex;
+-      struct list_head        inactive_list; /* link list for physical
+-                                              disk that belong in
+-                                              inactive volumes */
++      int              isRaid;                /* bit field, 1 if RAID */
+ } RaidCfgData;
+ /*
+- *  Adapter Structure - pci_dev specific.
++ * sas device info link list
+  */
++typedef struct _sas_device_info {
++      struct list_head list;
++      u64     SASAddress;
++      u8      TargetId;
++      u8      Bus;
++      u8      PhysicalPort;
++      u8      PhyNum;
++      u32     DeviceInfo;
++      u16     DevHandle;
++      u16     Flags;
++} sas_device_info_t;
++
++/*
++ * hba phy info array
++ */
++typedef struct _sas_phy_info {
++      u64     SASAddress;
++      u8      port;
++      u8      PortFlags;
++      u8      PhyFlags;
++      u8      NegotiatedLinkRate;
++      u16     ControllerDevHandle;
++      u16     devHandle;
++      u32     ControllerPhyDeviceInfo;
++      u8      phyId;
++      u8      hwLinkRate;
++      u8      reserved;
++} sas_phy_info_t;
++
+ /*
+- *  Adapter Structure - pci_dev specific.
++ *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
+  */
+ typedef struct _MPT_ADAPTER
+ {
+@@ -561,18 +547,13 @@ typedef struct _MPT_ADAPTER
+       SYSIF_REGS __iomem      *pio_chip;      /* Programmed IO (downloadboot) */
+       u8                       bus_type;      /* Parallel SCSI i/f */
+       u8                       pci_slot_number; /* ioc page 1 - pci slot number */
+-      u8                       ir_firmware; /* =1 if IR firmware detected */
+       u16                      deviceID;
+       u32                      mem_phys;      /* == f4020000 (mmap) */
+       u32                      pio_mem_phys;  /* Programmed IO (downloadboot) */
+       int                      mem_size;      /* mmap memory size */
+-      int                      sg_tablesize;  /* max SGE's per IO */
+-      int                      NumberOfBuses;
+-      int                      DevicesPerBus;
+       int                      alloc_total;
+       u32                      last_state;
+       int                      active;
+-      struct _MPT_DEVICE      *Target_List[MPT_MAX_BUSES];
+       u8                      *alloc;         /* frames alloc ptr */
+       dma_addr_t               alloc_dma;
+       u32                      alloc_sz;
+@@ -600,12 +581,7 @@ typedef struct _MPT_ADAPTER
+       int                      req_depth;     /* Number of request frames */
+       int                      req_sz;        /* Request frame size (bytes) */
+       spinlock_t               FreeQlock;
+-      spinlock_t               PendingMFlock;
+       struct list_head         FreeQ;
+-      MPT_FRAME_HDR           *PendingMF;
+-      struct scsi_cmnd        *PendingSCpnt;
+-      struct timer_list         TMtimer;      /* Timer for TM commands ONLY */
+-      MPT_FRAME_HDR            *tmPtr;        /* Ptr to TM request*/
+               /* Pool of SCSI sense buffers for commands coming from
+                * the SCSI mid-layer.  We have one 256 byte sense buffer
+                * for each REQ entry.
+@@ -638,12 +614,10 @@ typedef struct _MPT_ADAPTER
+       struct _MPT_ADAPTER     *alt_ioc;       /* ptr to 929 bound adapter port */
+       spinlock_t               diagLock;      /* diagnostic reset lock */
+       int                      diagPending;
+-      int                      IOCResetInProgress;
+       u32                      biosVersion;   /* BIOS version from IO Unit Page 2 */
+       int                      eventTypes;    /* Event logging parameters */
+       int                      eventContext;  /* Next event context */
+       struct _mpt_ioctl_events *events;       /* pointer to event log */
+-      EventNotification_t     *evnp;          /* event message frame pointer */
+       u8                      *cached_fw;     /* Pointer to FW */
+       dma_addr_t              cached_fw_dma;
+       struct list_head         configQ;       /* linked list of config. requests */
+@@ -662,12 +636,10 @@ typedef struct _MPT_ADAPTER
+ /* emoore@lsil.com - sas support - start */
+       U64                      sas_port_WWID[4];
+       u8                       BoardTracerNumber[16];
++      u8                       numPhys;
+       u16                      vendorID;
+-#if defined(CPQ_CIM)
+-      struct list_head         sas_device_info_list;
+-      struct semaphore         sas_device_info_mutex;
+-      u32                      num_ports;
+-#endif
++      sas_phy_info_t           *sasPhyInfo;
++      struct list_head         sasDeviceList;
+       struct semaphore         hot_plug_semaphore;
+       struct work_struct       mptscsih_persistTask;
+       struct timer_list        persist_timer; /* persist table timer */
+@@ -680,7 +652,7 @@ typedef struct _MPT_ADAPTER
+       u32                      PciState[64];     /* save PCI state to this area */
+ #endif
+ #if defined(CPQ_CIM)
+-      u32         csmi_change_count;    /* count to track all IR events for CSMI */
++    u32         csmi_change_count;    /* count to track all IR events for CSMI */
+ #endif
+       /*  
+        * Description: errata_flag_1064
+@@ -694,11 +666,7 @@ typedef struct _MPT_ADAPTER
+       u8                       upload_fw;     /* If set, do a fw upload */
+       u8                       reload_fw;     /* Force a FW Reload on next reset */
+       u8                       NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */
+-      u8                       pad1;
+-      u8                       CheckFcLinkSpeed;
+-      u8                       FcLinkSpeedCheckNeeded;
+-      u8                       FcLinkSpeed;
+-      MPT_FRAME_HDR           *FcLinkSpeedReqActive;
++      u8                       pad1[4];
+       int                      DoneCtx;
+       int                      TaskCtx;
+       int                      InternalCtx;
+@@ -811,25 +779,6 @@ typedef struct _mpt_sge {
+ #define DBG_DUMP_EVENT_REQUEST_FRAME(mfp)
+ #endif
+-#ifdef MPT_DEBUG_PEND
+-#define dpendprintk(x)  printk x
+-#define DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mfp) \
+-      {       int  i, n = ioc->req_sz/4;                                              \
+-              u32 *m = (u32 *)(mfp);                                  \
+-              for (i=0; i<n; i++) {                                   \
+-                      if (i && ((i%8)==0))                            \
+-                              printk("\n");                           \
+-                      printk("%08x ", le32_to_cpu(m[i]));             \
+-              }                                                       \
+-              printk("\n");                                           \
+-      }
+-#else
+-#define dpendprintk(x)
+-#define DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mfp)
+-#endif
+-
+-
+-
+ #ifdef MPT_DEBUG_HOTPLUG
+ #define dhotpprintk(x)  printk x
+ #else
+@@ -838,51 +787,16 @@ typedef struct _mpt_sge {
+ #ifdef MPT_DEBUG_RESET
+ #define drsprintk(x)  printk x
+-#define DBG_DUMP_RESET_REQUEST_FRAME(ioc, mfp) \
+-       {       int  i, n = ioc->req_sz/4;                                              \
+-               u32 *m = (u32 *)(mfp);                                  \
+-               for (i=0; i<n; i++) {                                   \
+-                       if (i && ((i%8)==0))                            \
+-                               printk("\n");                           \
+-                       printk("%08x ", le32_to_cpu(m[i]));             \
+-               }                                                       \
+-               printk("\n");                                           \
+-       }
+ #else
+ #define drsprintk(x)
+-#define DBG_DUMP_RESET_REQUEST_FRAME(ioc, mfp)
+ #endif
+ //#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME)
+ #if defined(MPT_DEBUG_MSG_FRAME)
+ #define dmfprintk(x)  printk x
+-#define DBG_DUMP_REQUEST_FRAME(ioc,mfp) \
+-      {       int  i, n = ioc->req_sz/4;
+-              u32 *m = (u32 *)(mfp);                                  \
+-              for (i=0; i<n; i++) {                                   \
+-                      if (i && ((i%8)==0))                            \
+-                              printk("\n");                           \
+-                      printk("%08x ", le32_to_cpu(m[i]));             \
+-              }                                                       \
+-              printk("\n");                                           \
+-      }
+-#else
+-#define dmfprintk(x)
+-#define DBG_DUMP_REQUEST_FRAME(ioc,mfp)
+-#endif
+-
+-#if defined(MPT_DEBUG_IOS)
+-#define dioprintk(x)  printk x
+-#else
+-#define dioprintk(x)
+-#endif
+-
+-
+-#if defined(MPT_DEBUG_CSMI)
+-#define DBG_DUMP_CSMI_FRAME(mfp) \
++#define DBG_DUMP_REQUEST_FRAME(mfp) \
+       {       int  i, n = 24;                                         \
+               u32 *m = (u32 *)(mfp);                                  \
+-              printk("CSMI MessageFrame:\n");                 \
+               for (i=0; i<n; i++) {                                   \
+                       if (i && ((i%8)==0))                            \
+                               printk("\n");                           \
+@@ -891,7 +805,8 @@ typedef struct _mpt_sge {
+               printk("\n");                                           \
+       }
+ #else
+-#define DBG_DUMP_CSMI_FRAME(mfp)
++#define dmfprintk(x)
++#define DBG_DUMP_REQUEST_FRAME(mfp)
+ #endif
+ #ifdef MPT_DEBUG_SG
+@@ -918,22 +833,28 @@ typedef struct _mpt_sge {
+ #define dnegoprintk(x)
+ #endif
++#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
++#define ddvtprintk(x)  printk x
++#else
++#define ddvtprintk(x)
++#endif
++
+ #ifdef MPT_DEBUG_IOCTL
+ #define dctlprintk(x) printk x
+ #else
+ #define dctlprintk(x)
+ #endif
+-#ifdef MPT_DEBUG_SAS
+-#define dsasprintk(x) printk x
++#ifdef MPT_DEBUG_REPLY
++#define dreplyprintk(x) printk x
+ #else
+-#define dsasprintk(x)
++#define dreplyprintk(x)
+ #endif
+-#ifdef MPT_DEBUG_CSMISAS
+-#define dcsmisasprintk(x) printk x
++#ifdef MPT_DEBUG_SAS
++#define dsasprintk(x) printk x
+ #else
+-#define dcsmisasprintk(x)
++#define dsasprintk(x)
+ #endif
+ #ifdef MPT_DEBUG_TM
+@@ -988,8 +909,7 @@ typedef struct _mpt_sge {
+ #define MPT_INDEX_2_RFPTR(ioc,idx) \
+       (MPT_FRAME_HDR*)( (u8*)(ioc)->reply_frames + (ioc)->req_sz * (idx) )
+-#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_MSG_FRAME) || defined(MPT_DEBUG_HANDSHAKE)
+-#define dreplyprintk(x) printk x
++#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) || defined(MPT_DEBUG_HANDSHAKE)
+ #define DBG_DUMP_REPLY_FRAME(mfp) \
+       {       u32 *m = (u32 *)(mfp);                                  \
+               int  i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16;     \
+@@ -1006,36 +926,9 @@ typedef struct _mpt_sge {
+                       printk(" %08x", le32_to_cpu(m[i]));             \
+               printk("\n");                                           \
+       }
+-#define DBG_DUMP_REPLYS_REQUEST_FRAME(ioc,mfp) \
+-      {       int  i, n = ioc->req_sz/4;;                                             \
+-              u32 *m = (u32 *)(mfp);                                  \
+-              for (i=0; i<n; i++) {                                   \
+-                      if (i && ((i%8)==0))                            \
+-                              printk("\n");                           \
+-                      printk("%08x ", le32_to_cpu(m[i]));             \
+-              }                                                       \
+-              printk("\n");                                           \
+-      }
+-#define DBG_DUMP_SENSE_DATA(mfp) \
+-      {       int  i, n = 8;                                          \
+-              u32 *m = (u32 *)(mfp);                                  \
+-              printk(KERN_INFO "SENSE DATA: ");                                       \
+-              for (i=0; i<n; i++)                                     \
+-                      printk(" %08x", le32_to_cpu(m[i]));             \
+-              printk("\n");                                           \
+-      }
+ #else
+-#define dreplyprintk(x)
+ #define DBG_DUMP_REPLY_FRAME(mfp)
+ #define DBG_DUMP_REQUEST_FRAME_HDR(mfp)
+-#define DBG_DUMP_REPLYS_REQUEST_FRAME(ioc,mfp)
+-#define DBG_DUMP_SENSE_DATA(mfp)
+-#endif
+-
+-#if defined (MPT_DEBUG_ERROR) || defined(MPT_DEBUG_REPLY)
+-#define derrprintk(x) printk x
+-#else
+-#define derrprintk(x)
+ #endif
+@@ -1095,34 +988,32 @@ typedef struct _MPT_SCSI_HOST {
+       u32                       pad0;
+       struct scsi_cmnd        **ScsiLookup;
+       struct scsi_device       *device;
++      VirtDevice              **Targets;
+       MPT_LOCAL_REPLY          *pLocal;               /* used for internal commands */
+-      struct timer_list         InternalCmdTimer;
++      struct timer_list         timer;
+               /* Pool of memory for holding SCpnts before doing
+                * OS callbacks. freeQ is the free pool.
+                */
+       u8                        tmPending;
+       u8                        resetPending;
++      u8                        negoNvram;            /* DV disabled, nego NVRAM */
++      u8                        pad1;
+       u8                        tmState;
+-      u8                        rsvd[4];
++      u8                        rsvd[2];
+       MPT_FRAME_HDR            *cmdPtr;               /* Ptr to nonOS request */
+       struct scsi_cmnd         *abortSCpnt;
+       MPT_LOCAL_REPLY           localReply;           /* internal cmd reply struct */
+       unsigned long             hard_resets;          /* driver forced bus resets count */
+       unsigned long             soft_resets;          /* fw/external bus resets count */
+       unsigned long             timeouts;             /* cmd timeouts */
+-      ushort                    sel_timeout[MPT_MAX_SCSI_DEVICES];
++      ushort                    sel_timeout[MPT_MAX_FC_DEVICES];
+       char                      *info_kbuf;
+       wait_queue_head_t         scandv_waitq;
+       int                       scandv_wait_done;
+-      wait_queue_head_t         TM_waitq;
+-      int                       TM_wait_done;
+       long                      last_queue_full;
+-      u8                        mpt_pq_filter;
+-      u16                       tm_iocstatus;
+-      struct list_head          target_reset_list;
++      u8                        mpt_pq_filter;
+ } MPT_SCSI_HOST;
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+  *    More Dynamic Multi-Pathing stuff...
+@@ -1176,29 +1067,20 @@ extern void     mpt_free_msg_frame(MPT_ADAP
+ extern void    mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
+ extern void    mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
+-extern int     mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes,
+-u32 *req, ulong timeout, int sleepFlag);
+-
++extern int     mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag);
+ extern int     mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
+ extern u32     mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
+ extern void    mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
+ extern int     mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
+-
+-extern int       mpt_SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
+-extern void      mptscsih_TM_timeout(unsigned long data);
+-
+ extern int     mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
+-extern int       mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
+-extern int       mpt_writeSDP1(MPT_ADAPTER *ioc, int portnum, int id, int flags);
+-extern void  mpt_setSDP1parameters (u8 width, u8 factor, u8 offset, u8 flags, int *requestedPtr, int *configurationPtr);
+ extern void    mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
+ extern void    mpt_free_fw_memory(MPT_ADAPTER *ioc);
+ extern int     mpt_findImVolumes(MPT_ADAPTER *ioc);
+ extern int     mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
+ extern int     mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
++extern int     mpt_sas_get_info(MPT_ADAPTER *ioc);
++extern void    mpt_poll_interrupt(MPT_ADAPTER *ioc);
+ extern int     mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
+-extern void      mpt_poll_interrupt(MPT_ADAPTER *ioc);
+-extern int     mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk);
+ /*
+  *  Public data decl's...
+@@ -1237,7 +1119,7 @@ extern int               mpt_sg_tablesize;
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ #endif                /* } __KERNEL__ */
+-#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) || defined(__powerpc__)
++#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__)
+ #define CAST_U32_TO_PTR(x)    ((void *)(u64)x)
+ #define CAST_PTR_TO_U32(x)    ((u32)(u64)x)
+ #else
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.c linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.c 2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.c        2007-11-02 09:10:23.000000000 +0100
+@@ -4,8 +4,8 @@
+  *      For use with LSI Logic PCI chip/adapters
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -57,6 +57,9 @@
+ #include <linux/miscdevice.h>
+ #include <linux/smp_lock.h>
+ #include <linux/compat.h>
++#if defined(CPQ_CIM)
++#include "csmisas.h"
++#endif // CPQ_CIM
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+@@ -67,16 +70,11 @@
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_tcq.h>
+-#define COPYRIGHT     "Copyright (c) 1999-2007 LSI Logic Corporation"
++#define COPYRIGHT     "Copyright (c) 1999-2005 LSI Logic Corporation"
+ #define MODULEAUTHOR  "LSI Logic Corporation"
+ #include "mptbase.h"
+ #include "mptctl.h"
+-#if defined(CPQ_CIM)
+-#include "mptsas.h"
+-#include "csmi/csmisas.h"
+-#endif // CPQ_CIM
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ #define my_NAME               "Fusion MPT misc device (ioctl) driver"
+ #define my_VERSION    MPT_LINUX_VERSION_COMMON
+@@ -85,12 +83,10 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ extern        int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
+-extern int    mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait, int sleepFlag);
+ static int mptctl_id = -1;
+@@ -119,10 +115,6 @@ static int mptctl_eventenable(unsigned l
+ static int mptctl_eventreport(unsigned long arg);
+ static int mptctl_replace_fw(unsigned long arg);
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-static int mptctl_hba_pciinfo(unsigned long arg);
+-#endif
+-
+ 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);
+@@ -133,29 +125,27 @@ static int mptctl_unregister_diag_buffer
+ static int mptctl_query_diag_buffer(unsigned long arg);
+ static int mptctl_read_diag_buffer(unsigned long arg);
+ #if defined(CPQ_CIM)
+-static int csmisas_get_driver_info(unsigned long arg);
+-static int csmisas_get_cntlr_status(unsigned long arg);
+-static int csmisas_get_cntlr_config(unsigned long arg);
+-static int csmisas_get_phy_info(unsigned long arg);
+-static int csmisas_get_scsi_address(unsigned long arg);
+-static int csmisas_get_link_errors(unsigned long arg);
+-static int csmisas_smp_passthru(unsigned long arg);
+-static int csmisas_firmware_download(unsigned long arg);
+-static int csmisas_get_raid_info(unsigned long arg);
+-static int csmisas_get_raid_config(unsigned long arg);
+-static int csmisas_get_raid_features(unsigned long arg);
+-static int csmisas_set_raid_control(unsigned long arg);
+-static int csmisas_get_raid_element(unsigned long arg);
+-static int csmisas_set_raid_operation(unsigned long arg);
+-static int csmisas_set_phy_info(unsigned long arg);
+-static int csmisas_ssp_passthru(unsigned long arg);
+-static int csmisas_stp_passthru(unsigned long arg);
+-static int csmisas_get_sata_signature(unsigned long arg);
+-static int csmisas_get_device_address(unsigned long arg);
+-static int csmisas_task_managment(unsigned long arg);
+-static int csmisas_phy_control(unsigned long arg);
+-static int csmisas_get_connector_info(unsigned long arg);
+-static int csmisas_get_location(unsigned long arg);
++static int mptctl_csmi_sas_get_driver_info(unsigned long arg);
++static int mptctl_csmi_sas_get_cntlr_status(unsigned long arg);
++static int mptctl_csmi_sas_get_cntlr_config(unsigned long arg);
++static int mptctl_csmi_sas_get_phy_info(unsigned long arg);
++static int mptctl_csmi_sas_get_scsi_address(unsigned long arg);
++static int mptctl_csmi_sas_get_link_errors(unsigned long arg);
++static int mptctl_csmi_sas_smp_passthru(unsigned long arg);
++static int mptctl_csmi_sas_firmware_download(unsigned long arg);
++static int mptctl_csmi_sas_get_raid_info(unsigned long arg);
++static int mptctl_csmi_sas_get_raid_config(unsigned long arg);
++static int mptctl_csmi_sas_get_raid_features(unsigned long arg);
++static int mptctl_csmi_sas_get_raid_control(unsigned long arg);
++static int mptctl_csmi_sas_set_phy_info(unsigned long arg);
++static int mptctl_csmi_sas_ssp_passthru(unsigned long arg);
++static int mptctl_csmi_sas_stp_passthru(unsigned long arg);
++static int mptctl_csmi_sas_get_sata_signature(unsigned long arg);
++static int mptctl_csmi_sas_get_device_address(unsigned long arg);
++static int mptctl_csmi_sas_task_managment(unsigned long arg);
++static int mptctl_csmi_sas_phy_control(unsigned long arg);
++static int mptctl_csmi_sas_get_connector_info(unsigned long arg);
++static int mptctl_csmi_sas_get_location(unsigned long arg);
+ #endif // CPQ_CIM
+ static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
+@@ -230,7 +220,7 @@ static inline int
+ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
+ {
+       int rc = 0;
+-      dctlprintk((KERN_INFO MYNAM ": mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
++      dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
+       if (nonblock) {
+               if (down_trylock(&ioc->ioctl->sem_ioc))
+@@ -239,7 +229,7 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, in
+               if (down_interruptible(&ioc->ioctl->sem_ioc))
+                       rc = -ERESTARTSYS;
+       }
+-      dctlprintk((KERN_INFO MYNAM ": mptctl_syscall_down return %d\n", rc));
++      dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
+       return rc;
+ }
+@@ -304,17 +294,9 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME
+               if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
+                       (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+-
+-                      dcsmisasprintk(("\tiocstatus = 0x%x, "
+-                              "scsi_status = 0x%x, scsi_state = 0x%x\n",
+-                              reply->u.sreply.IOCStatus,
+-                              reply->u.sreply.SCSIStatus,
+-                              reply->u.sreply.SCSIState));
+-
+                       ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
+                       if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
+-                                (iocStatus == MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH) ||
+                               (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
+                               ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
+                       }
+@@ -438,8 +420,8 @@ mptctl_bus_reset(MPT_IOCTL *ioctl)
+                       ioctl->ioc->name, mf));
+       pScsiTm = (SCSITaskMgmt_t *) mf;
+-      pScsiTm->TargetID = ioctl->id;
+-      pScsiTm->Bus = ioctl->bus;
++      pScsiTm->TargetID = ioctl->target;
++      pScsiTm->Bus = hd->port;        /* 0 */
+       pScsiTm->ChainOffset = 0;
+       pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+       pScsiTm->Reserved = 0;
+@@ -460,7 +442,7 @@ mptctl_bus_reset(MPT_IOCTL *ioctl)
+       ioctl->wait_done=0;
+       if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
+-          sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,10, CAN_SLEEP)) != 0) {
++           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));
+@@ -652,7 +634,7 @@ __mptctl_ioctl(struct file *file, unsign
+       dctlprintk(("mptctl_ioctl() called with cmd=%x\n", cmd));
+       if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
+-              printk(KERN_ERR "%s: mptctl_ioctl() @%d - "
++              printk(KERN_ERR "%s::mptctl_ioctl() @%d - "
+                               "Unable to copy mpt_ioctl_header data @ %p\n",
+                               __FILE__, __LINE__, uhdr);
+               return -EFAULT;
+@@ -693,38 +675,28 @@ __mptctl_ioctl(struct file *file, unsign
+               return mptctl_query_diag_buffer(arg);
+       } else if (cmd == MPTDIAGUNREGISTER) {
+               return mptctl_unregister_diag_buffer(arg);
+-
+-      }
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-       else if (cmd == MPTHBAPCIINFO) {
+-              return mptctl_hba_pciinfo(arg);
+       }
+-#endif
+ #if defined(CPQ_CIM)
+       else if (cmd == CC_CSMI_SAS_GET_DRIVER_INFO) {
+-              return csmisas_get_driver_info(arg);
++              return mptctl_csmi_sas_get_driver_info(arg);
+       } else if (cmd == CC_CSMI_SAS_GET_CNTLR_CONFIG) {
+-              return csmisas_get_cntlr_config(arg);
++              return mptctl_csmi_sas_get_cntlr_config(arg);
+       } else if (cmd == CC_CSMI_SAS_GET_CNTLR_STATUS) {
+-              return csmisas_get_cntlr_status(arg);
++              return mptctl_csmi_sas_get_cntlr_status(arg);
+       } else if (cmd == CC_CSMI_SAS_GET_SCSI_ADDRESS) {
+-              return csmisas_get_scsi_address(arg);
++              return mptctl_csmi_sas_get_scsi_address(arg);
+       } else if (cmd == CC_CSMI_SAS_GET_DEVICE_ADDRESS){
+-              return csmisas_get_device_address(arg);
++              return mptctl_csmi_sas_get_device_address(arg);
+       }
+ #endif // CPQ_CIM
+-      dctlprintk(("mptctl_ioctl() called with cmd=%x, interrupt required\n", cmd));
+       /* All of these commands require an interrupt or
+        * are unknown/illegal.
+        */
+-      if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) {
+-              dctlprintk(("mptctl_ioctl() called with cmd=%x ret=%d, syscall_down failed\n", cmd, ret));
++      if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
+               return ret;
+-      }
+-      dctlprintk(("mptctl_ioctl() called with cmd=%x, syscall_down completed\n", cmd));
+       if (cmd == MPTFWDOWNLOAD)
+               ret = mptctl_fw_download(arg);
+       else if (cmd == MPTFWDOWNLOADBOOT)
+@@ -745,41 +717,37 @@ __mptctl_ioctl(struct file *file, unsign
+               ret = mptctl_read_diag_buffer(arg);
+ #if defined(CPQ_CIM)
+       else if (cmd == CC_CSMI_SAS_GET_PHY_INFO)
+-              ret = csmisas_get_phy_info(arg);
++              ret = mptctl_csmi_sas_get_phy_info(arg);
+       else if (cmd == CC_CSMI_SAS_GET_SATA_SIGNATURE)
+-              ret = csmisas_get_sata_signature(arg);
++              ret = mptctl_csmi_sas_get_sata_signature(arg);
+       else if (cmd == CC_CSMI_SAS_GET_LINK_ERRORS)
+-              ret = csmisas_get_link_errors(arg);
++              ret = mptctl_csmi_sas_get_link_errors(arg);
+       else if (cmd == CC_CSMI_SAS_SMP_PASSTHRU)
+-              ret = csmisas_smp_passthru(arg);
++              ret = mptctl_csmi_sas_smp_passthru(arg);
+       else if (cmd == CC_CSMI_SAS_SSP_PASSTHRU)
+-              ret = csmisas_ssp_passthru(arg);
++              ret = mptctl_csmi_sas_ssp_passthru(arg);
+       else if (cmd == CC_CSMI_SAS_FIRMWARE_DOWNLOAD)
+-              ret = csmisas_firmware_download(arg);
++              ret = mptctl_csmi_sas_firmware_download(arg);
+       else if (cmd == CC_CSMI_SAS_GET_RAID_INFO)
+-              ret = csmisas_get_raid_info(arg);
++              ret = mptctl_csmi_sas_get_raid_info(arg);
+       else if (cmd == CC_CSMI_SAS_GET_RAID_CONFIG)
+-              ret = csmisas_get_raid_config(arg);
+-      else if (cmd == CC_CSMI_SAS_GET_RAID_FEATURES)
+-              ret = csmisas_get_raid_features(arg);
+-      else if (cmd == CC_CSMI_SAS_SET_RAID_CONTROL)
+-              ret = csmisas_set_raid_control(arg);
+-      else if (cmd == CC_CSMI_SAS_GET_RAID_ELEMENT)
+-              ret = csmisas_get_raid_element(arg);
+-      else if (cmd == CC_CSMI_SAS_SET_RAID_OPERATION)
+-              ret = csmisas_set_raid_operation(arg);
++              ret = mptctl_csmi_sas_get_raid_config(arg);
++    else if (cmd == CC_CSMI_SAS_GET_RAID_FEATURES)
++              ret = mptctl_csmi_sas_get_raid_features(arg);
++    else if (cmd == CC_CSMI_SAS_SET_RAID_CONTROL)
++              ret = mptctl_csmi_sas_get_raid_control(arg);
+       else if (cmd == CC_CSMI_SAS_SET_PHY_INFO)
+-              ret = csmisas_set_phy_info(arg);
++              ret = mptctl_csmi_sas_set_phy_info(arg);
+       else if (cmd == CC_CSMI_SAS_STP_PASSTHRU)
+-              ret = csmisas_stp_passthru(arg);
++              ret = mptctl_csmi_sas_stp_passthru(arg);
+       else if (cmd == CC_CSMI_SAS_TASK_MANAGEMENT)
+-              ret = csmisas_task_managment(arg);
++              ret = mptctl_csmi_sas_task_managment(arg);
+       else if (cmd == CC_CSMI_SAS_PHY_CONTROL)
+-              ret = csmisas_phy_control(arg);
++              ret = mptctl_csmi_sas_phy_control(arg);
+       else if (cmd == CC_CSMI_SAS_GET_CONNECTOR_INFO)
+-              ret = csmisas_get_connector_info(arg);
++              ret = mptctl_csmi_sas_get_connector_info(arg);
+       else if (cmd == CC_CSMI_SAS_GET_LOCATION)
+-              ret = csmisas_get_location(arg);
++              ret = mptctl_csmi_sas_get_location(arg);
+ #endif // CPQ_CIM
+       else {
+               dctlprintk(("mptctl_ioctl() cmd=%x not found\n", cmd));
+@@ -788,7 +756,6 @@ __mptctl_ioctl(struct file *file, unsign
+       up(&iocp->ioctl->sem_ioc);
+-      dctlprintk(("mptctl_ioctl() called with cmd=%x ret=%d, up completed\n", cmd, ret));
+       return ret;
+ }
+@@ -813,7 +780,7 @@ static int mptctl_do_reset(unsigned long
+       dctlprintk(("mptctl_do_reset called.\n"));
+       if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
+-              printk(KERN_ERR "%s@%d: mptctl_do_reset - "
++              printk(KERN_ERR "%s@%d::mptctl_do_reset - "
+                               "Unable to copy mpt_ioctl_diag_reset struct @ %p\n",
+                               __FILE__, __LINE__, urinfo);
+               return -EFAULT;
+@@ -858,7 +825,7 @@ mptctl_fw_download(unsigned long arg)
+       dctlprintk(("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 - "
++              printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
+                               "Unable to copy mpt_fw_xfer struct @ %p\n",
+                               __FILE__, __LINE__, ufwdl);
+               return -EFAULT;
+@@ -1014,7 +981,7 @@ mptctl_do_fw_download(int ioc, char __us
+                       mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
+                       n++;
+                       if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
+-                              printk(KERN_ERR "%s@%d: _ioctl_fwdl - "
++                              printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
+                                               "Unable to copy f/w buffer hunk#%d @ %p\n",
+                                               __FILE__, __LINE__, n, ufwbuf);
+                               goto fwdl_out;
+@@ -1040,9 +1007,6 @@ mptctl_do_fw_download(int ioc, char __us
+        * Finally, perform firmware download.
+        */
+       ReplyMsg = NULL;
+-      iocp->ioctl->wait_done = 0;
+-      INITIALIZE_IOCTL_STATUS(iocp->ioctl->status)
+-
+       mpt_put_msg_frame(mptctl_id, iocp, mf);
+       /* Now wait for the command to complete */
+@@ -1075,7 +1039,7 @@ mptctl_do_fw_download(int ioc, char __us
+               printk(KERN_WARNING MYNAM ": (try again later?)\n");
+               return -EBUSY;
+       } else {
+-              printk(KERN_WARNING MYNAM ": ioctl_fwdl() ERROR!  %s returned [bad] status = %04xh\n",
++              printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR!  %s returned [bad] status = %04xh\n",
+                                   iocp->name, iocstat);
+               printk(KERN_WARNING MYNAM ": (bad VooDoo)\n");
+               return -ENOMSG;
+@@ -1111,7 +1075,7 @@ mptctl_fw_downloadboot(unsigned long arg
+       dctlprintk(("mptctl_fwdlboot 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 - "
++              printk(KERN_ERR "%s@%d::_ioctl_fwdl - "
+                               "Unable to copy mpt_fw_xfer struct @ %p\n",
+                               __FILE__, __LINE__, ufwdl);
+               return -EFAULT;
+@@ -1149,20 +1113,11 @@ mptctl_do_fw_downloadboot(int ioc_num, c
+               return -ENODEV; /* (-6) No such device or address */
+       }
+-      pbuf = (char *)__get_free_pages(GFP_KERNEL, get_order(fwlen));
+-       if (pbuf==NULL) {
+-               printk(KERN_ERR "%s@%d: _ioctl_fwdlboot - "
+-                               "Unable to allocate memory\n",
+-                               __FILE__, __LINE__);
+-               return -ENOMEM;
+-       }
+-
+-
+-if (copy_from_user(pbuf, ufwbuf, fwlen)) {
+-              printk(KERN_ERR "%s@%d: _ioctl_fwdlboot - "
++      pbuf = kmalloc(fwlen, GFP_KERNEL);
++      if (copy_from_user(pbuf, ufwbuf, fwlen)) {
++              printk(KERN_ERR "%s@%d::_ioctl_fwdlboot - "
+                               "Unable to copy mpt_fw @ %p\n",
+                               __FILE__, __LINE__, (void*)ufwbuf);
+-free_pages((unsigned long)pbuf, get_order(fwlen));
+               return -EFAULT;
+       }
+@@ -1171,10 +1126,7 @@ free_pages((unsigned long)pbuf, get_orde
+       rc = mpt_downloadboot(ioc, (MpiFwHeader_t *)pbuf, CAN_SLEEP);
+       ddlprintk((MYIOC_s_INFO_FMT "mptctl_do_fw_downloadboot rc=%x\n",
+-
+                               ioc->name, rc));
+-#if 0
+-
+       if ( (rc == 0) && (ioc->bus_type == SAS) ) {
+ /*            if ((rc = mptctl_syscall_down(ioc, nonblock)) != 0)
+                       return rc; */
+@@ -1194,12 +1146,10 @@ free_pages((unsigned long)pbuf, get_orde
+                       ioc->name));
+               } */
+       }
+-#endif
+-free_pages((unsigned long)pbuf, get_order(fwlen));
++      kfree(pbuf);
+       return rc;
+ }
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+  * SGE Allocation routine
+@@ -1278,9 +1228,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
+               if (buflist[buflist_ent].kptr == NULL) {
+                       alloc_sz = alloc_sz / 2;
+                       if (alloc_sz == 0) {
+-                              printk(KERN_WARNING MYNAM ": -SG: No can do - "
++                              printk(KERN_WARNING MYNAM "-SG: No can do - "
+                                                   "not enough memory!   :-(\n");
+-                              printk(KERN_WARNING MYNAM ": -SG: (freeing %d frags)\n",
++                              printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
+                                                   numfrags);
+                               goto free_and_fail;
+                       }
+@@ -1304,17 +1254,17 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
+               /* Need to chain? */
+               if (fragcnt == sg_spill) {
+-                      printk(KERN_WARNING MYNAM ": -SG: No can do - " "Chain required!   :-(\n");
+-                      printk(KERN_WARNING MYNAM ": (freeing %d frags)\n", numfrags);
++                      printk(KERN_WARNING MYNAM "-SG: No can do - " "Chain required!   :-(\n");
++                      printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags);
+                       goto free_and_fail;
+               }
+               /* overflow check... */
+               if (numfrags*8 > MAX_SGL_BYTES){
+                       /* GRRRRR... */
+-                      printk(KERN_WARNING MYNAM ": -SG: No can do - "
++                      printk(KERN_WARNING MYNAM "-SG: No can do - "
+                                           "too many SG frags!   :-(\n");
+-                      printk(KERN_WARNING MYNAM ": -SG: (freeing %d frags)\n",
++                      printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",
+                                           numfrags);
+                       goto free_and_fail;
+               }
+@@ -1435,16 +1385,18 @@ mptctl_getiocinfo (unsigned long arg, un
+       struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_iocinfo *karg;
+       MPT_ADAPTER             *ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+-      VirtDevice              *pTarget;
+       struct pci_dev          *pdev;
++      struct Scsi_Host        *sh;
++      MPT_SCSI_HOST           *hd;
+       int                     iocnum;
+       int                     numDevices = 0;
+-      int                     id, bus;
++      unsigned int            max_id;
++      int                     ii;
+       unsigned int            port;
+       int                     cim_rev;
+       u8                      revision;
++      dctlprintk(("mptctl_getiocinfo called.\n"));
+       /* Add of PCI INFO results in unaligned access for
+        * IA64 and Sparc. Reset long to int. Return no PCI
+        * data for obsolete format.
+@@ -1457,20 +1409,18 @@ mptctl_getiocinfo (unsigned long arg, un
+               cim_rev = 2;
+       else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12))
+               cim_rev = 0;    /* obsolete */
+-      else {
+-              dctlprintk(("mptctl_getiocinfo called.i Invalid data_size=%d\n", data_size));
++      else
+               return -EFAULT;
+-      }
+       karg = kmalloc(data_size, GFP_KERNEL);
+       if (karg == NULL) {
+-              printk(KERN_ERR "%s: mpt_ioctl_iocinfo() @%d - no memory available!\n",
++              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 - "
++              printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
+                       "Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
+                               __FILE__, __LINE__, (void*)uarg);
+               kfree(karg);
+@@ -1484,11 +1434,10 @@ mptctl_getiocinfo (unsigned long arg, un
+               kfree(karg);
+               return -ENODEV;
+       }
+-      dctlprintk(("ioc%d: mptctl_getiocinfo called.\n", iocnum));
+       /* Verify the data transfer size is correct. */
+       if (karg->hdr.maxDataSize != data_size) {
+-              printk(KERN_ERR "%s@%d: mptctl_getiocinfo - "
++              printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
+                       "Structure size mismatch. Command not completed.\n",
+                               __FILE__, __LINE__);
+               kfree(karg);
+@@ -1535,11 +1484,18 @@ mptctl_getiocinfo (unsigned long arg, un
+       /* Get number of devices
+          */
+-      for (bus = 0; bus < ioc->NumberOfBuses; bus++) {
+-              if ((pMptTarget = ioc->Target_List[bus])) {
+-                      for (id = 0; id < ioc->DevicesPerBus; id++) {
+-                              pTarget = pMptTarget->Target[id];
+-                              if (pTarget)
++      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++;
+                       }
+               }
+@@ -1563,7 +1519,7 @@ mptctl_getiocinfo (unsigned long arg, un
+       /* Copy the data from kernel memory to user memory
+        */
+       if (copy_to_user((char __user *)arg, karg, data_size)) {
+-              printk(KERN_ERR "%s@%d: mptctl_getiocinfo - "
++              printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
+                       "Unable to write out mpt_ioctl_iocinfo struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               kfree(karg);
+@@ -1590,22 +1546,25 @@ mptctl_gettargetinfo (unsigned long arg)
+       struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_targetinfo karg;
+       MPT_ADAPTER             *ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+-      VirtDevice              *pTarget;
++      struct Scsi_Host        *sh;
++      MPT_SCSI_HOST           *hd;
++      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                     maxWordsLeft;
+       int                     numBytes;
+-      u8                      port, devType, bus;
++      u8                      port, devType, bus_id;
++      dctlprintk(("mptctl_gettargetinfo called.\n"));
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
+-              printk(KERN_ERR "%s@%d: mptctl_gettargetinfo - "
++              printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
+                       "Unable to read in mpt_ioctl_targetinfo struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -1618,7 +1577,6 @@ mptctl_gettargetinfo (unsigned long arg)
+               return -ENODEV;
+       }
+-      dctlprintk(("ioc%ds: mptctl_gettargetinfo called.\n", iocnum));
+       /* Get the port number and set the maximum number of bytes
+        * in the returned structure.
+        * Ignore the port setting.
+@@ -1628,7 +1586,7 @@ mptctl_gettargetinfo (unsigned long arg)
+       port = karg.hdr.port;
+       if (maxWordsLeft <= 0) {
+-              printk(KERN_ERR "%s: mptctl_gettargetinfo() @%d - no memory available!\n",
++              printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
+                               __FILE__, __LINE__);
+               return -ENOMEM;
+       }
+@@ -1649,7 +1607,7 @@ mptctl_gettargetinfo (unsigned long arg)
+        */
+       pmem = kmalloc(numBytes, GFP_KERNEL);
+       if (pmem == NULL) {
+-              printk(KERN_ERR "%s: mptctl_gettargetinfo() @%d - no memory available!\n",
++              printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
+                               __FILE__, __LINE__);
+               return -ENOMEM;
+       }
+@@ -1658,68 +1616,71 @@ mptctl_gettargetinfo (unsigned long arg)
+       /* Get number of devices
+          */
+-      /* Check all of the target structures.
+-       * Save the Id and increment the counter,
+-       * if ptr non-null.
+-       */
+-      mpt_findImVolumes(ioc);
+-      pIoc2 = ioc->raid_data.pIocPg2;
+-      for (bus = 0; bus < ioc->NumberOfBuses; bus++) {
+-              for ( id = 0; id < ioc->DevicesPerBus; ) {
+-                      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;
+-                                      if ( bus == pIoc2->RaidVolume[0].VolumeBus) {
+-                                              numDevices++;
+-                                              *pdata = ( (devType << 24) | (bus<< 8) | id );
++      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++;
++                                              pdata++;
+                                               --maxWordsLeft;
+                                               goto next_id;
+-                                      }
+-                              } else {
+-                                      pIoc3 = ioc->raid_data.pIocPg3;
+-                                      for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
+-                                              if ((pIoc3->PhysDisk[jj].PhysDiskID == id) && (pIoc3->PhysDisk[jj].PhysDiskBus == bus))
+-                                                      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 ((pMptTarget = ioc->Target_List[bus])) {
+-                              pTarget = pMptTarget->Target[id];
+-                              if (pTarget) {
++                              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 (pTarget->luns[lun_index] & 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);
++                      "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
+                                                               goto data_space_full;
+                                                       }
+-                                                      bus = pTarget->bus;
++                                                      bus_id = vdev->bus_id;
+                                                       numDevices++;
+-                                                      *pdata = ( (jj << 16) | (bus << 8) | id );
++                                                      *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));
++              "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
+                                                       pdata++;
+                                                       --maxWordsLeft;
+                                               }
+                                       }
+                               }
+-                      }
+ next_id:
+-                      id++;
++                              id++;
++                      }
+               }
+       }
+ data_space_full:
+@@ -1729,7 +1690,7 @@ data_space_full:
+        */
+       if (copy_to_user((char __user *)arg, &karg,
+                               sizeof(struct mpt_ioctl_targetinfo))) {
+-              printk(KERN_ERR "%s@%d: mptctl_gettargetinfo - "
++              printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
+                       "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               kfree(pmem);
+@@ -1739,7 +1700,7 @@ data_space_full:
+       /* Copy the remaining data from kernel memory to user memory
+        */
+       if (copy_to_user(uarg->targetInfo, pmem, numBytes)) {
+-              printk(KERN_ERR "%s@%d: mptctl_gettargetinfo - "
++              printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "
+                       "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
+                               __FILE__, __LINE__, pdata);
+               kfree(pmem);
+@@ -1751,70 +1712,6 @@ data_space_full:
+       return 0;
+ }
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*
+- *    mptctl_hba_pciinfo - Obtain all mpt HBAs pci (Config Space) information.
+- *    @arg: User space argument
+- *
+- * Outputs:   None.
+- * Return:    0 if successful
+- *            -EFAULT if data unavailable
+- */
+-static int
+-mptctl_hba_pciinfo (unsigned long arg)
+-{
+-      struct mpt_ioctl_hbapciinfo *uarg = (struct mpt_ioctl_hbapciinfo *) arg;
+-      struct mpt_ioctl_hbapciinfo karg;
+-
+-      MPT_ADAPTER     *ioc;
+-      int             ioc_num=0, data_size;
+-      u8                      revision;
+-
+-      data_size = sizeof(mpt_ioctl_header)+4;
+-      /* Clear the struct before filling in data. */
+-      memset( &karg, 0, (uarg->hdr.maxDataSize + data_size) );
+-
+-      dctlprintk((KERN_INFO MYNAM ": Checking for MPT adapters...maxDataSize=%d data_size=%d\n", uarg->hdr.maxDataSize, data_size));
+-
+-      list_for_each_entry(ioc,&ioc_list,list) {
+-              data_size += sizeof (struct mpt_ioctl_mptpciinfo);
+-              if ( data_size >= uarg->hdr.maxDataSize ) {
+-                      dctlprintk((KERN_INFO MYNAM ": data_size=%d >= maxDataSize=%d\n", data_size, uarg->hdr.maxDataSize));
+-                      break;
+-              }
+-              karg.hbapciinfo[ioc_num].iocNumber = ioc_num;
+-              karg.hbapciinfo[ioc_num].deviceID = ioc->deviceID;
+-              karg.hbapciinfo[ioc_num].vendorID = ioc->vendorID;
+-
+-              pci_read_config_byte(ioc->pcidev, PCI_CLASS_REVISION, &revision);
+-
+-              karg.hbapciinfo[ioc_num].subSystemVendorID = ioc->pcidev->subsystem_vendor;
+-              karg.hbapciinfo[ioc_num].subSystemID = ioc->pcidev->subsystem_device;
+-
+-              karg.hbapciinfo[ioc_num].revisionID = revision;
+-              mpt_GetIocState(ioc, 1);
+-              karg.hbapciinfo[ioc_num++].iocState = (ioc->last_state >> MPI_IOC_STATE_SHIFT);
+-      }
+-
+-      karg.totalIOC = ioc_num;
+-
+-      dctlprintk((KERN_INFO MYNAM ": %d MPT adapters found, arg=%p karg=%p size=%d\n",
+-               karg.totalIOC, (char *)arg, &karg, (int)sizeof(struct mpt_ioctl_hbapciinfo)));
+-
+-      /* Copy the data from kernel memory to user memory
+-       */
+-      if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_hbapciinfo))) {
+-              printk(KERN_ERR "%s@%d::mptctl_eventquery - "
+-                      "Unable to write out mpt_ioctl_eventquery struct @ %p\n",
+-                              __FILE__, __LINE__, (void*)uarg);
+-              return -EFAULT;
+-      }
+-      return 0;
+-}
+-#endif
+-
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /* MPT IOCTL Test function.
+  *
+@@ -1833,7 +1730,7 @@ mptctl_readtest (unsigned long arg)
+       dctlprintk(("mptctl_readtest called.\n"));
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
+-              printk(KERN_ERR "%s@%d: mptctl_readtest - "
++              printk(KERN_ERR "%s@%d::mptctl_readtest - "
+                       "Unable to read in mpt_ioctl_test struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -1863,7 +1760,7 @@ mptctl_readtest (unsigned long arg)
+       /* Copy the data from kernel memory to user memory
+        */
+       if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) {
+-              printk(KERN_ERR "%s@%d: mptctl_readtest - "
++              printk(KERN_ERR "%s@%d::mptctl_readtest - "
+                       "Unable to write out mpt_ioctl_test struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -1893,7 +1790,7 @@ mptctl_eventquery (unsigned long arg)
+       dctlprintk(("mptctl_eventquery called.\n"));
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
+-              printk(KERN_ERR "%s@%d: mptctl_eventquery - "
++              printk(KERN_ERR "%s@%d::mptctl_eventquery - "
+                       "Unable to read in mpt_ioctl_eventquery struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -1912,7 +1809,7 @@ mptctl_eventquery (unsigned long arg)
+       /* Copy the data from kernel memory to user memory
+        */
+       if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) {
+-              printk(KERN_ERR "%s@%d: mptctl_eventquery - "
++              printk(KERN_ERR "%s@%d::mptctl_eventquery - "
+                       "Unable to write out mpt_ioctl_eventquery struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -1931,7 +1828,7 @@ mptctl_eventenable (unsigned long arg)
+       dctlprintk(("mptctl_eventenable called.\n"));
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
+-              printk(KERN_ERR "%s@%d: mptctl_eventenable - "
++              printk(KERN_ERR "%s@%d::mptctl_eventenable - "
+                       "Unable to read in mpt_ioctl_eventenable struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -1978,7 +1875,7 @@ mptctl_eventreport (unsigned long arg)
+       dctlprintk(("mptctl_eventreport called.\n"));
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
+-              printk(KERN_ERR "%s@%d: mptctl_eventreport - "
++              printk(KERN_ERR "%s@%d::mptctl_eventreport - "
+                       "Unable to read in mpt_ioctl_eventreport struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -2010,7 +1907,7 @@ mptctl_eventreport (unsigned long arg)
+        */
+       numBytes = max * sizeof(MPT_IOCTL_EVENTS);
+       if (copy_to_user(uarg->eventData, ioc->events, numBytes)) {
+-              printk(KERN_ERR "%s@%d: mptctl_eventreport - "
++              printk(KERN_ERR "%s@%d::mptctl_eventreport - "
+                       "Unable to write out mpt_ioctl_eventreport struct @ %p\n",
+                               __FILE__, __LINE__, ioc->events);
+               return -EFAULT;
+@@ -2031,7 +1928,7 @@ mptctl_replace_fw (unsigned long arg)
+       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 - "
++              printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
+                       "Unable to read in mpt_ioctl_replace_fw struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -2067,7 +1964,7 @@ mptctl_replace_fw (unsigned long arg)
+       /* Copy the data from user memory to kernel space
+        */
+       if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
+-              printk(KERN_ERR "%s@%d: mptctl_replace_fw - "
++              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);
+@@ -2104,7 +2001,7 @@ mptctl_mpt_command (unsigned long arg)
+       dctlprintk(("mptctl_command called.\n"));
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) {
+-              printk(KERN_ERR "%s@%d: mptctl_mpt_command - "
++              printk(KERN_ERR "%s@%d::mptctl_mpt_command - "
+                       "Unable to read in mpt_ioctl_command struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -2149,11 +2046,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+       int             iocnum, flagsLength;
+       int             sz, rc = 0;
+       int             msgContext;
+-      u16             req_idx=0;
++      u16             req_idx;
+       ulong           timeout;
+-        MPT_FRAME_HDR   *SAS_handshake_mf=NULL;
+-        char            *SAS_handshake_reply=NULL;
+-        u16             msgSize=0;
++
++      dctlprintk(("mptctl_do_mpt_command called.\n"));
+       bufIn.kptr = bufOut.kptr = NULL;
+       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+@@ -2162,14 +2058,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+                               iocnum));
+               return -ENODEV;
+       }
+-      dctlprintk(("ioc%d: mptctl_do_mpt_command called.\n", iocnum));
+       if (!ioc->ioctl) {
+-              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++              printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       "No memory available during driver init.\n",
+                               __FILE__, __LINE__);
+               return -ENOMEM;
+       } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
+-              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++              printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       "Busy with IOC Reset \n", __FILE__, __LINE__);
+               return -EBUSY;
+       }
+@@ -2183,7 +2078,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+               sz += sizeof(dma_addr_t) + sizeof(u32);
+       if (sz > ioc->req_sz) {
+-              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++              printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       "Request frame too large (%d) maximum (%d)\n",
+                               __FILE__, __LINE__, sz, ioc->req_sz);
+               return -EFAULT;
+@@ -2191,44 +2086,18 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+       /* Get a free request frame and save the message context.
+        */
+-      if (((MPIHeader_t *)(mfPtr))->MsgContext == 0x02012020) {
+-              msgSize = karg.hdr.port >> 16;
+-              if ( (mf = (MPT_FRAME_HDR *)kmalloc(msgSize, GFP_KERNEL)) == NULL) {
+-                      dfailprintk(("%s: mptctl_do_mpt_command, Unable to kmalloc msgSize=%d for SAS_handshake!!\n",
+-                      ioc->name, msgSize));
+-                      return -ENOMEM;
+-              }
+-              SAS_handshake_mf = mf;
+-              if (karg.maxReplyBytes) {
+-                      if ( (SAS_handshake_reply = (char *)kmalloc(karg.maxReplyBytes, GFP_KERNEL)) == NULL) {
+-                              kfree(SAS_handshake_mf);
+-                              dfailprintk(("%s: mptctl_do_mpt_command, Unable to kmalloc maxReplyBytes=%d for SAS_handshake!!\n",
+-                                      ioc->name, karg.maxReplyBytes));
+-                              return -ENOMEM;
+-                      }
+-              }
+-              hdr = (MPIHeader_t *) mf;
+-              msgContext = le32_to_cpu(0x02012020);
+-              karg.hdr.port &= 0x0000ffff;
+-      } else {
+-              if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
+-                      dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
+-                          ioc->name,__FUNCTION__));
+-                      return -EAGAIN;
+-              } else {
+-                      hdr = (MPIHeader_t *) mf;
+-                      msgContext = le32_to_cpu(hdr->MsgContext);
+-                      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-              }
+-      }
++        if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
++                return -EAGAIN;
++      hdr = (MPIHeader_t *) mf;
++      msgContext = le32_to_cpu(hdr->MsgContext);
++      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-//@@@@@
+       /* Copy the request frame
+        * Reset the saved message context.
+        */
+       if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) {
+-              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++              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;
+@@ -2259,34 +2128,17 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+       case MPI_FUNCTION_SCSI_IO_REQUEST:
+               if (ioc->sh) {
+                       SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
+-                      struct _MPT_DEVICE      *pMptTarget;
+                       VirtDevice      *pTarget = NULL;
+                       MPT_SCSI_HOST   *hd = NULL;
+                       int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
+                       int scsidir = 0;
+-                      int id = (int) pScsiReq->TargetID;
+-                      int bus = (int) pScsiReq->Bus;
++                      int target = (int) pScsiReq->TargetID;
+                       int dataSize;
+-                      if ((id < 0) || (id > ioc->DevicesPerBus)) {
+-                              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
+-                                      "Target ID=%d out of bounds.  DevicesPerBus=%d\n",
+-                                      __FILE__, __LINE__, id, ioc->DevicesPerBus);
+-                              rc = -ENODEV;
+-                              goto done_free_mem;
+-                      }
+-
+-                      if ((bus < 0) || (bus >= ioc->NumberOfBuses)) {
+-                              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
+-                                      "Target Bus=%d out of bounds.  NumberOfBuses=%d\n",
+-                                      __FILE__, __LINE__, bus, ioc->NumberOfBuses);
+-                              rc = -ENODEV;
+-                              goto done_free_mem;
+-                      }
+-                      if ((pMptTarget = ioc->Target_List[bus]) == NULL) {
+-                              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
+-                                      "Target_List=NULL for %s bus=%d\n",
+-                                      __FILE__, __LINE__, ioc->name, bus);
++                      if ((target < 0) || (target >= ioc->sh->max_id)) {
++                              printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
++                                      "Target ID out of bounds. \n",
++                                      __FILE__, __LINE__);
+                               rc = -ENODEV;
+                               goto done_free_mem;
+                       }
+@@ -2310,7 +2162,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+                                  + (req_idx * MPT_SENSE_BUFFER_ALLOC));
+                       if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) {
+-                              pTarget = pMptTarget->Target[id];
++                              if (hd->Targets)
++                                      pTarget = hd->Targets[target];
+                       }
+                       if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+@@ -2331,10 +2184,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+                       pScsiReq->DataLength = cpu_to_le32(dataSize);
+                       ioc->ioctl->reset = MPTCTL_RESET_OK;
+-                      ioc->ioctl->id = id;
++                      ioc->ioctl->target = target;
+               } else {
+-                      printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++                      printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               "SCSI driver is not loaded. \n",
+                                       __FILE__, __LINE__);
+                       rc = -EFAULT;
+@@ -2353,7 +2206,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+       case MPI_FUNCTION_SATA_PASSTHROUGH:
+               if (!ioc->sh) {
+-                      printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++                      printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               "SCSI driver is not loaded. \n",
+                                       __FILE__, __LINE__);
+                       rc = -EFAULT;
+@@ -2409,10 +2262,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+                       pScsiReq->DataLength = cpu_to_le32(dataSize);
+                       ioc->ioctl->reset = MPTCTL_RESET_OK;
+-                      ioc->ioctl->id = pScsiReq->TargetID;
+-                      ioc->ioctl->bus = pScsiReq->Bus;
++                      ioc->ioctl->target = pScsiReq->TargetID;
+               } else {
+-                      printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++                      printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               "SCSI driver is not loaded. \n",
+                                       __FILE__, __LINE__);
+                       rc = -EFAULT;
+@@ -2424,7 +2276,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+               {
+                       MPT_SCSI_HOST *hd = NULL;
+                       if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) {
+-                              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++                              printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                                       "SCSI driver not loaded or SCSI host not found. \n",
+                                       __FILE__, __LINE__);
+                               rc = -EFAULT;
+@@ -2457,7 +2309,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+                               (pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||
+                               (pInit->HostMfaHighAddr != high_addr) ||
+                               (pInit->SenseBufferHighAddr != sense_high)) {
+-                              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++                              printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                                       "IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n",
+                                       __FILE__, __LINE__);
+                               rc = -EFAULT;
+@@ -2490,7 +2342,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+                       MPI_FUNCTION_LAN_RESET
+               */
+-              printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++              printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                       "Illegal request (function 0x%x) \n",
+                       __FILE__, __LINE__, hdr->Function);
+               rc = -EFAULT;
+@@ -2550,7 +2402,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+                                               karg.dataOutBufPtr,
+                                               bufOut.len)) {
+                                       printk(KERN_ERR
+-                                              "%s@%d: mptctl_do_mpt_command - Unable "
++                                              "%s@%d::mptctl_do_mpt_command - Unable "
+                                               "to read user data "
+                                               "struct @ %p\n",
+                                               __FILE__, __LINE__,karg.dataOutBufPtr);
+@@ -2561,7 +2413,16 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+               }
+               if (karg.dataInSize > 0) {
+-                      flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
++                      if ((karg.dataOutSize > 0) &&
++                          (hdr->Function == MPI_FUNCTION_SMP_PASSTHROUGH)){
++                              flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
++                                              MPI_SGE_FLAGS_END_OF_BUFFER |
++                                              MPI_SGE_FLAGS_DIRECTION |
++                                              mpt_addr_size() )
++                                              << MPI_SGE_FLAGS_SHIFT;
++                      } else {
++                              flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
++                      }
+                       flagsLength |= karg.dataInSize;
+                       bufIn.len = karg.dataInSize;
+@@ -2585,14 +2446,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+       }
+       ioc->ioctl->wait_done = 0;
+-      INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+       if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
+               DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
+               if (mpt_send_handshake_request(mptctl_id, ioc,
+-                  sizeof(SCSITaskMgmt_t), (u32*)mf,10, CAN_SLEEP) != 0) {
++                      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));
+@@ -2600,73 +2460,27 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+                       rc = -ENODATA;
+                       goto done_free_mem;
+               }
+-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 */
+-                       mptctl_free_tm_flags(ioc);
+-                       mptctl_timeout_expired(ioc->ioctl);
+-                       rc = -ENODATA;
+-                       goto done_free_mem;
+-               }
+-} else {
+-               if ( SAS_handshake_mf ) {
+-                       dctlprintk(("SAS_handshake_message Function=%x\n",
+-                               hdr->Function));
+-
+-                       timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
+-                       rc = mpt_handshake_req_reply_wait(ioc,
+-                               msgSize,
+-                               (u32*)SAS_handshake_mf,
+-                              karg.maxReplyBytes,
+-                              (u16*)SAS_handshake_reply, timeout /*seconds*/,
+-                               CAN_SLEEP);
+-                       kfree(SAS_handshake_mf);
+-                       SAS_handshake_mf = NULL;
+-              if (rc == 0) {
+-              dctlprintk(("SAS_handshake_message Function=%x completed successfully\n",
+-                               hdr->Function));
+-                               sz = karg.maxReplyBytes;
+-                               if (sz > 0) {
+-                    if (copy_to_user((char *)karg.replyFrameBufPtr,SAS_handshake_reply, sz)){
+-printk(KERN_ERR "%s@%d::mptctl_do_mpt_command -" "Unable to write out reply frame %p\n",__FILE__, __LINE__, (void*)karg.replyFrameBufPtr);
+-                               rc =  -ENODATA;
+-                              }
+-                       }else {
+-
+-                                rc =  -ENODATA;
+-                               dctlprintk(("SAS_handshake_message failed sz=%d\n", sz));
+-                                }
+-                               kfree(SAS_handshake_reply);
+-                               SAS_handshake_reply = NULL;
+-                               goto done_free_mem;
+-                             }
+-                            else
+-                            {
+-                               rc = -ENODATA;
+-                               kfree(SAS_handshake_reply);
+-                               SAS_handshake_reply = NULL;
+-                               goto done_free_mem;
+-                            }
+-                         }else {
+-                               mpt_put_msg_frame(mptctl_id, ioc, mf);
+-                       /* 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);
++      } else
++              mpt_put_msg_frame(mptctl_id, ioc, mf);
+-                if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
++      /* 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;
+               goto done_free_mem;
+-             }
+-       }
+-}
++      }
++
+       mf = NULL;
+@@ -2684,7 +2498,7 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co
+                       if (copy_to_user(karg.replyFrameBufPtr,
+                                &ioc->ioctl->ReplyFrame, sz)){
+-                               printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++                               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                                "Unable to write out reply frame %p\n",
+                                __FILE__, __LINE__, karg.replyFrameBufPtr);
+                                rc =  -ENODATA;
+@@ -2699,7 +2513,7 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co
+               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 - "
++                              printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               "Unable to write sense data to user %p\n",
+                               __FILE__, __LINE__,
+                               karg.senseDataPtr);
+@@ -2716,7 +2530,7 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co
+                               (karg.dataInSize > 0) && (bufIn.kptr)) {
+               if (copy_to_user(karg.dataInBufPtr,
+                        bufIn.kptr, karg.dataInSize)) {
+-                      printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - "
++                      printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                               "Unable to write data to user %p\n",
+                               __FILE__, __LINE__,
+                               karg.dataInBufPtr);
+@@ -2726,6 +2540,10 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co
+ 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) {
+@@ -2738,14 +2556,6 @@ done_free_mem:
+                       bufIn.len, (void *) bufIn.kptr, dma_addr_in);
+       }
+-if (SAS_handshake_mf) {
+-              kfree(SAS_handshake_mf);
+-              mf=NULL;
+-      }
+-if (SAS_handshake_reply)
+-              kfree(SAS_handshake_reply);
+-
+-
+       /* mf is null if command issued successfully
+        * otherwise, failure occured after mf acquired.
+        */
+@@ -2792,7 +2602,7 @@ mptctl_hp_hostinfo(unsigned long arg, un
+               return -EFAULT;
+       if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
+-              printk(KERN_ERR "%s@%d: mptctl_hp_host_info - "
++              printk(KERN_ERR "%s@%d::mptctl_hp_host_info - "
+                       "Unable to read in hp_host_info struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -2914,8 +2724,6 @@ mptctl_hp_hostinfo(unsigned long arg, un
+           (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
+       ioc->ioctl->wait_done = 0;
+-      INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+       mpt_put_msg_frame(mptctl_id, ioc, mf);
+       rc = wait_event_timeout(mptctl_wait,
+@@ -2947,7 +2755,7 @@ mptctl_hp_hostinfo(unsigned long arg, un
+       /* Copy the data from kernel memory to user memory
+        */
+       if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) {
+-              printk(KERN_ERR "%s@%d: mptctl_hpgethostinfo - "
++              printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - "
+                       "Unable to write out hp_host_info @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -2986,7 +2794,7 @@ mptctl_hp_targetinfo(unsigned long arg)
+       dctlprintk(("mptctl_hp_targetinfo called.\n"));
+       if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) {
+-              printk(KERN_ERR "%s@%d: mptctl_hp_targetinfo - "
++              printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - "
+                       "Unable to read in hp_host_targetinfo struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -3097,7 +2905,7 @@ mptctl_hp_targetinfo(unsigned long arg)
+       /* Copy the data from kernel memory to user memory
+        */
+       if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) {
+-              printk(KERN_ERR "%s@%d: mptctl_hp_target_info - "
++              printk(KERN_ERR "%s@%d::mptctl_hp_target_info - "
+                       "Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
+                               __FILE__, __LINE__, uarg);
+               return -EFAULT;
+@@ -3231,8 +3039,6 @@ allocDiagBuffer:
+       DiagBufferPostRequest->BufferAddress.Low = cpu_to_le32(tmp);
+       ioc->ioctl->wait_done = 0;
+-      INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+       mpt_put_msg_frame(mptctl_id, ioc, mf);
+       /* Now wait for the command to complete */
+@@ -3275,6 +3081,10 @@ allocDiagBuffer:
+ mptctl_register_diag_buffer_out:
++      ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++          MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++          MPT_IOCTL_STATUS_RF_VALID );
++
+       if ( rc ) {
+               pci_free_consistent(ioc->pcidev, request_data_sz,
+                       request_data,
+@@ -3371,8 +3181,6 @@ mptctl_release_diag_buffer (unsigned lon
+       DiagRelease->MsgFlags = 0;
+       ioc->ioctl->wait_done = 0;
+-      INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+       mpt_put_msg_frame(mptctl_id, ioc, mf);
+       /* Now wait for the command to complete */
+@@ -3410,6 +3218,10 @@ mptctl_release_diag_buffer (unsigned lon
+ mptctl_release_diag_buffer_out:
++      ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++          MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++          MPT_IOCTL_STATUS_RF_VALID);
++
+       return rc;
+ }
+@@ -3706,8 +3518,6 @@ mptctl_read_diag_buffer (unsigned long a
+               DiagBufferPostRequest->BufferAddress.Low = cpu_to_le32(tmp);
+               ioc->ioctl->wait_done = 0;
+-              INITIALIZE_IOCTL_STATUS(ioc->ioctl->status)
+-
+               mpt_put_msg_frame(mptctl_id, ioc, mf);
+               /* Now wait for the command to complete */
+@@ -3746,8 +3556,14 @@ mptctl_read_diag_buffer (unsigned long a
+                               ioc->ioctl->status));
+                       rc = -EFAULT;
+               }
+-      }
++
+ mptctl_read_diag_buffer_out:
++
++              ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED |
++                  MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
++                  MPT_IOCTL_STATUS_RF_VALID);
++
++      }
+       return rc;
+ }
+@@ -3796,7 +3612,7 @@ compat_mptctl_ioctl(unsigned int fd, uns
+       int ret;
+       lock_kernel();
+-      dctlprintk((KERN_INFO MYNAM ": compat_mptctl_ioctl() called\n"));
++      dctlprintk((KERN_INFO MYNAM "::compat_mptctl_ioctl() called\n"));
+       ret = mptctl_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+       unlock_kernel();
+       return ret;
+@@ -3820,7 +3636,7 @@ compat_mptfwxfer_ioctl(struct file *filp
+       int nonblock = (filp->f_flags & O_NONBLOCK);
+       int ret;
+-      dctlprintk((KERN_INFO MYNAM ": compat_mptfwxfer_ioctl() called\n"));
++      dctlprintk((KERN_INFO MYNAM "::compat_mptfwxfer_ioctl() called\n"));
+       if (copy_from_user(&kfw32, (char __user *)arg, sizeof(kfw32)))
+               return -EFAULT;
+@@ -3829,7 +3645,7 @@ compat_mptfwxfer_ioctl(struct file *filp
+       iocnumX = kfw32.iocnum & 0xFF;
+       if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
+           (iocp == NULL)) {
+-              dctlprintk((KERN_ERR MYNAM ": compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
++              dctlprintk((KERN_ERR MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
+                               __LINE__, iocnumX));
+               return -ENODEV;
+       }
+@@ -3866,7 +3682,7 @@ compat_mpt_command(struct file *filp, un
+       int nonblock = (filp->f_flags & O_NONBLOCK);
+       int ret;
+-      dctlprintk((KERN_INFO MYNAM ": compat_mpt_command() called\n"));
++      dctlprintk((KERN_INFO MYNAM "::compat_mpt_command() called\n"));
+       if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32)))
+               return -EFAULT;
+@@ -3875,7 +3691,7 @@ compat_mpt_command(struct file *filp, un
+       iocnumX = karg32.hdr.iocnum & 0xFF;
+       if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
+           (iocp == NULL)) {
+-              dctlprintk((KERN_ERR MYNAM ": compat_mpt_command @%d - ioc%d not found!\n",
++              dctlprintk((KERN_ERR MYNAM "::compat_mpt_command @%d - ioc%d not found!\n",
+                               __LINE__, iocnumX));
+               return -ENODEV;
+       }
+@@ -4087,14 +3903,6 @@ static int __init mptctl_init(void)
+       if (++where && err) goto out_fail;
+       err = register_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_CONFIG, compat_mptctl_ioctl);
+       if (++where && err) goto out_fail;
+-      err = register_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_FEATURES, compat_mptctl_ioctl);
+-      if (++where && err) goto out_fail;
+-      err = register_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_CONTROL, compat_mptctl_ioctl);
+-      if (++where && err) goto out_fail;
+-      err = register_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_ELEMENT, compat_mptctl_ioctl);
+-      if (++where && err) goto out_fail;
+-      err = register_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_OPERATION, compat_mptctl_ioctl);
+-      if (++where && err) goto out_fail;
+       err = register_ioctl32_conversion(CC_CSMI_SAS_SET_PHY_INFO, compat_mptctl_ioctl);
+       if (++where && err) goto out_fail;
+       err = register_ioctl32_conversion(CC_CSMI_SAS_STP_PASSTHRU, compat_mptctl_ioctl);
+@@ -4185,10 +3993,6 @@ out_fail:
+       unregister_ioctl32_conversion(CC_CSMI_SAS_FIRMWARE_DOWNLOAD);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_INFO);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_CONFIG);
+-      unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_FEATURES);
+-      unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_CONTROL);
+-      unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_ELEMENT);
+-      unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_OPERATION);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_SET_PHY_INFO);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_STP_PASSTHRU);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_TASK_MANAGEMENT);
+@@ -4260,10 +4064,6 @@ static void mptctl_exit(void)
+       unregister_ioctl32_conversion(CC_CSMI_SAS_FIRMWARE_DOWNLOAD);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_INFO);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_CONFIG);
+-      unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_FEATURES);
+-      unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_CONTROL);
+-      unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_ELEMENT);
+-      unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_OPERATION);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_SET_PHY_INFO);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_STP_PASSTHRU);
+       unregister_ioctl32_conversion(CC_CSMI_SAS_TASK_MANAGEMENT);
+@@ -4277,7 +4077,7 @@ static void mptctl_exit(void)
+ }
+ #if defined(CPQ_CIM)
+-#include "csmi/csmisas.c"
++#include "csmisas.c"
+ #endif // CPQ_CIM
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.h linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.h 2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.h        2007-11-02 09:10:23.000000000 +0100
+@@ -5,8 +5,8 @@
+  *          LSIFC9xx/LSI409xx Fibre Channel
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptctl.h,v 1.14 2003/03/18 22:49:51 Exp $
+  */
+@@ -59,6 +59,7 @@
+  */
+ #define MPT_MISCDEV_BASENAME            "mptctl"
+ #define MPT_MISCDEV_PATHNAME            "/dev/" MPT_MISCDEV_BASENAME
++#define MPT_CSMI_DESCRIPTION          "LSI Logic Corporation: Fusion MPT Driver "MPT_LINUX_VERSION_COMMON
+ #define MPT_PRODUCT_LENGTH              12
+@@ -94,16 +95,6 @@
+ #define MPTDIAGQUERY          _IOWR(MPT_MAGIC_NUMBER,29,mpt_diag_query_t)
+ #define MPTDIAGREADBUFFER     _IOWR(MPT_MAGIC_NUMBER,30,mpt_diag_read_buffer_t)
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-#define MPTHBAPCIINFO         _IOWR(MPT_MAGIC_NUMBER,31,struct mpt_ioctl_hbapciinfo)
+-#endif
+-
+-
+-#define INITIALIZE_IOCTL_STATUS(status) \
+-      status &= ~( MPT_IOCTL_STATUS_COMMAND_GOOD \
+-      | MPT_IOCTL_STATUS_SENSE_VALID \
+-      | MPT_IOCTL_STATUS_RF_VALID);
+-
+ /*
+  * SPARC PLATFORM REMARKS:
+  * IOCTL data structures that contain pointers
+@@ -314,28 +305,6 @@ typedef struct mpt_ioctl_replace_fw {
+       u8               newImage[1];
+ } mpt_ioctl_replace_fw_t;
+-#ifdef MPT_SUPPORT_FWDLB_IOCTL
+-struct mpt_ioctl_mptpciinfo {
+-    U8  iocNumber;
+-    U8  iocState;
+-    U8  revisionID;
+-    U8  reserved1;
+-    U16 vendorID;
+-    U16 deviceID;
+-    U16 subSystemVendorID;
+-    U16 subSystemID;
+-};
+-
+-
+-struct mpt_ioctl_hbapciinfo {
+-      mpt_ioctl_header     hdr;
+-    U8                   totalIOC;
+-    U8                   reserved[3];
+-    struct mpt_ioctl_mptpciinfo hbapciinfo[18];
+-};
+-#endif
+-
+-
+ /* General MPT Pass through data strucutre
+  *
+  * iocnum
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptfc.c linux-2.6.9-55.0.12/drivers/message/fusion/mptfc.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptfc.c  2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptfc.c 2007-11-02 09:10:23.000000000 +0100
+@@ -3,8 +3,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -74,7 +74,6 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ /* Command line args */
+ static int mpt_pq_filter = 0;
+@@ -131,7 +130,7 @@ static struct scsi_host_template mptfc_d
+       .bios_param                     = mptscsih_bios_param,
+       .can_queue                      = MPT_FC_CAN_QUEUE,
+       .this_id                        = -1,
+-      .sg_tablesize                   = CONFIG_FUSION_MAX_SGE,
++      .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
+       .max_sectors                    = 8192,
+       .cmd_per_lun                    = 7,
+       .use_clustering                 = ENABLE_CLUSTERING,
+@@ -161,8 +160,6 @@ static struct pci_device_id mptfc_pci_ta
+               PCI_ANY_ID, PCI_ANY_ID },
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
+               PCI_ANY_ID, PCI_ANY_ID },
+-        { 0x1657, MPI_MANUFACTPAGE_DEVICEID_FC949E,
+-                PCI_ANY_ID, PCI_ANY_ID },
+       {0}     /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
+@@ -184,6 +181,8 @@ mptfc_probe(struct pci_dev *pdev, const 
+       MPT_ADAPTER             *ioc;
+       unsigned long            flags;
+       int                      sz, ii;
++      int                      numSGE = 0;
++      int                      scale;
+       int                      ioc_cap;
+       u8                      *mem;
+       int                     error=0;
+@@ -262,16 +261,46 @@ mptfc_probe(struct pci_dev *pdev, const 
+               ioc->name, mpt_can_queue, ioc->req_depth,
+               sh->can_queue));
+-      sh->max_id = ioc->DevicesPerBus;
++      sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
+       sh->max_lun = MPT_LAST_LUN + 1;
+-      sh->max_channel = ioc->NumberOfBuses - 1;
++      sh->max_channel = 0;
+       sh->this_id = ioc->pfacts[0].PortSCSIID;
++
+       /* Required entry.
+        */
+       sh->unique_id = ioc->id;
+-      sh->sg_tablesize = ioc->sg_tablesize;
++
++      /* Verify that we won't exceed the maximum
++       * number of chain buffers
++       * We can optimize:  ZZ = req_sz/sizeof(SGE)
++       * For 32bit SGE's:
++       *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
++       *               + (req_sz - 64)/sizeof(SGE)
++       * A slightly different algorithm is required for
++       * 64bit SGEs.
++       */
++      scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
++      if (sizeof(dma_addr_t) == sizeof(u64)) {
++              numSGE = (scale - 1) *
++                (ioc->facts.MaxChainDepth-1) + scale +
++                (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
++                sizeof(u32));
++      } else {
++              numSGE = 1 + (scale - 1) *
++                (ioc->facts.MaxChainDepth-1) + scale +
++                (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
++                sizeof(u32));
++      }
++
++      if (numSGE < sh->sg_tablesize) {
++              /* Reset this value */
++              dprintk((MYIOC_s_INFO_FMT
++                "Resetting sg_tablesize to %d from %d\n",
++                ioc->name, numSGE, sh->sg_tablesize));
++              sh->sg_tablesize = numSGE;
++      }
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+       /* Set the pci device pointer in Scsi_Host structure.
+@@ -300,24 +329,23 @@ mptfc_probe(struct pci_dev *pdev, const 
+       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+                ioc->name, hd->ScsiLookup, sz));
+-      for (ii=0; ii < ioc->NumberOfBuses; ii++) {
+-              /* Allocate memory for the device structures.
+-               * A non-Null pointer at an offset
+-               * indicates a device exists.
+-               */
+-              sz = ioc->DevicesPerBus * sizeof(void *);
+-              mem = kmalloc(sz, GFP_ATOMIC);
+-              if (mem == NULL) {
+-                      error = -ENOMEM;
+-                      goto out_mptfc_probe;
+-              }
++      /* Allocate memory for the device structures.
++       * A non-Null pointer at an offset
++       * indicates a device exists.
++       * max_id = 1 + maximum id (hosts.h)
++       */
++      sz = sh->max_id * sizeof(void *);
++      mem = kmalloc(sz, GFP_ATOMIC);
++      if (mem == NULL) {
++              error = -ENOMEM;
++              goto out_mptfc_probe;
++      }
+-              memset(mem, 0, sz);
+-              ioc->Target_List[ii] = (struct _MPT_DEVICE *) mem;
++      memset(mem, 0, sz);
++      hd->Targets = (VirtDevice **) mem;
+-              dinitprintk((KERN_INFO
+-                " For Bus=%d, Target_List=%p sz=%d\n", ii, mem, sz));
+-      }
++      dprintk((KERN_INFO
++        "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+       /* Clear the TM flags
+        */
+@@ -333,17 +361,13 @@ mptfc_probe(struct pci_dev *pdev, const 
+        */
+       hd->cmdPtr = NULL;
+-      /* Initialize this IOC's timers
++      /* Initialize this SCSI Hosts' timers
+        * To use, set the timer expires field
+-       * and add_timer. Used for internally
+-         * generated commands.
++       * and add_timer
+        */
+-        init_timer(&hd->InternalCmdTimer);
+-      hd->InternalCmdTimer.data = (unsigned long) hd;
+-      hd->InternalCmdTimer.function = mptscsih_InternalCmdTimer_expired;
+-        init_timer(&ioc->TMtimer);
+-      ioc->TMtimer.data = (unsigned long) ioc;
+-      ioc->TMtimer.function = mptscsih_TM_timeout;
++      init_timer(&hd->timer);
++      hd->timer.data = (unsigned long) hd;
++      hd->timer.function = mptscsih_timer_expired;
+       hd->mpt_pq_filter = mpt_pq_filter;
+@@ -356,9 +380,6 @@ mptfc_probe(struct pci_dev *pdev, const 
+       hd->scandv_wait_done = 0;
+       hd->last_queue_full = 0;
+-        init_waitqueue_head(&hd->TM_waitq);
+-        hd->TM_wait_done = 0;
+-
+       error = scsi_add_host (sh, &ioc->pcidev->dev);
+       if(error) {
+               dprintk((KERN_ERR MYNAM
+@@ -394,60 +415,6 @@ static struct pci_driver mptfc_driver = 
+ };
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-int
+-mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+-{
+-      MPT_SCSI_HOST *hd;
+-      u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+-
+-      devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to FC host driver!\n",
+-                      ioc->name, event));
+-
+-      if (ioc->sh == NULL ||
+-              ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+-              return 1;
+-
+-      switch (event) {
+-      case MPI_EVENT_UNIT_ATTENTION:                  /* 03 */
+-              /* FIXME! */
+-              break;
+-      case MPI_EVENT_IOC_BUS_RESET:                   /* 04 */
+-      case MPI_EVENT_EXT_BUS_RESET:                   /* 05 */
+-              if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
+-                      hd->soft_resets++;
+-              break;
+-      case MPI_EVENT_LOGOUT:                          /* 09 */
+-              /* FIXME! */
+-              break;
+-
+-              /*
+-               *  CHECKME! Don't think we need to do
+-               *  anything for these, but...
+-               */
+-      case MPI_EVENT_RESCAN:                          /* 06 */
+-      case MPI_EVENT_LINK_STATUS_CHANGE:              /* 07 */
+-      case MPI_EVENT_LOOP_STATE_CHANGE:               /* 08 */
+-              /*
+-               *  CHECKME!  Falling thru...
+-               */
+-              break;
+-
+-      case MPI_EVENT_NONE:                            /* 00 */
+-      case MPI_EVENT_LOG_DATA:                        /* 01 */
+-      case MPI_EVENT_STATE_CHANGE:                    /* 02 */
+-      case MPI_EVENT_EVENT_CHANGE:                    /* 0A */
+-      case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
+-      default:
+-              devtprintk((KERN_INFO "%s:  Ignoring event (=%02Xh)\n",
+-                      __FUNCTION__, event));
+-              break;
+-      }
+-
+-      return 1;               /* currently means nothing really */
+-}
+-
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+  *    mptfc_init - Register MPT adapter(s) as SCSI host(s) with
+  *    linux scsi mid-layer.
+@@ -464,9 +431,9 @@ mptfc_init(void)
+       mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
+       mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
+-        if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
++      if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
+               devtprintk((KERN_INFO MYNAM
+-                  ": mptfc_event_process Registered for IOC event notifications\n"));
++                ": Registered for IOC event notifications\n"));
+       }
+       if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
+@@ -488,7 +455,6 @@ mptfc_exit(void)
+ {
+       pci_unregister_driver(&mptfc_driver);
+-
+       mpt_reset_deregister(mptfcDoneCtx);
+       dprintk((KERN_INFO MYNAM
+         ": Deregistered for IOC reset notifications\n"));
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.c linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.c 2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.c        2007-11-02 09:10:23.000000000 +0100
+@@ -4,7 +4,7 @@
+  *      For use with LSI Logic Fibre Channel PCI chip/adapters
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 2000-2007 LSI Logic Corporation
++ *  Copyright (c) 2000-2005 LSI Logic Corporation
+  *
+  *  $Id: mptlan.c,v 1.55 2003/05/07 14:08:32 Exp $
+  */
+@@ -57,11 +57,9 @@
+ #include <linux/module.h>
+ #include <linux/fs.h>
+-#define my_VERSION    MPT_LINUX_VERSION_COMMON
+ #define MYNAM         "mptlan"
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+@@ -185,16 +183,16 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+       struct net_device *dev = ioc->netdev;
+       int FreeReqFrame = 0;
+-      dlioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n",
++      dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n",
+                 IOC_AND_NETDEV_NAMES_s_s(dev)));
+-//    dlioprintk((KERN_INFO MYNAM "@lan_reply: mf = %p, reply = %p\n",
++//    dioprintk((KERN_INFO MYNAM "@lan_reply: mf = %p, reply = %p\n",
+ //                    mf, reply));
+       if (mf == NULL) {
+               u32 tmsg = CAST_PTR_TO_U32(reply);
+-              dlioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n",
++              dioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n",
+                               IOC_AND_NETDEV_NAMES_s_s(dev),
+                               tmsg));
+@@ -204,14 +202,14 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+               //  mptbase.c::mpt_interrupt() routine and callcack here
+ #if 0
+               case LAN_REPLY_FORM_MESSAGE_CONTEXT:
+-//                    dlioprintk((KERN_INFO MYNAM "/lan_reply: "
++//                    dioprintk((KERN_INFO MYNAM "/lan_reply: "
+ //                              "MessageContext turbo reply received\n"));
+                       FreeReqFrame = 1;
+                       break;
+ #endif
+               case LAN_REPLY_FORM_SEND_SINGLE:
+-//                    dlioprintk((MYNAM "/lan_reply: "
++//                    dioprintk((MYNAM "/lan_reply: "
+ //                              "calling mpt_lan_send_reply (turbo)\n"));
+                       //      FreeReqFrame = mpt_lan_send_turbo(dev, tmsg);
+@@ -230,7 +228,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+                       break;
+               case LAN_REPLY_FORM_RECEIVE_SINGLE:
+-//                    dlioprintk((KERN_INFO MYNAM "@lan_reply: "
++//                    dioprintk((KERN_INFO MYNAM "@lan_reply: "
+ //                              "rcv-Turbo = %08x\n", tmsg));
+                       mpt_lan_receive_post_turbo(dev, tmsg);
+                       break;
+@@ -248,10 +246,10 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+       }
+ //    msg = (u32 *) reply;
+-//    dlioprintk((KERN_INFO MYNAM "@lan_reply: msg = %08x %08x %08x %08x\n",
++//    dioprintk((KERN_INFO MYNAM "@lan_reply: msg = %08x %08x %08x %08x\n",
+ //              le32_to_cpu(msg[0]), le32_to_cpu(msg[1]),
+ //              le32_to_cpu(msg[2]), le32_to_cpu(msg[3])));
+-//    dlioprintk((KERN_INFO MYNAM "@lan_reply: Function = %02xh\n",
++//    dioprintk((KERN_INFO MYNAM "@lan_reply: Function = %02xh\n",
+ //              reply->u.hdr.Function));
+       switch (reply->u.hdr.Function) {
+@@ -275,7 +273,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
+                       if (!(pRecvRep->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY))
+                               FreeReqFrame = 1;
+               } else
+-                      dlioprintk((KERN_INFO MYNAM "@lan_reply: zero context "
++                      dioprintk((KERN_INFO MYNAM "@lan_reply: zero context "
+                                 "ReceivePostReply received.\n"));
+               break;
+       }
+@@ -617,7 +615,7 @@ mpt_lan_send_turbo(struct net_device *de
+       priv->stats.tx_packets++;
+       priv->stats.tx_bytes += sent->len;
+-      dlioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
++      dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
+                       IOC_AND_NETDEV_NAMES_s_s(dev),
+                       __FUNCTION__, sent));
+@@ -649,7 +647,7 @@ mpt_lan_send_reply(struct net_device *de
+       count = pSendRep->NumberOfContexts;
+-      dlioprintk((KERN_INFO MYNAM ": send_reply: IOCStatus: %04x\n",
++      dioprintk((KERN_INFO MYNAM ": send_reply: IOCStatus: %04x\n",
+                le16_to_cpu(pSendRep->IOCStatus)));
+       /* Add check for Loginfo Flag in IOCStatus */
+@@ -683,7 +681,7 @@ mpt_lan_send_reply(struct net_device *de
+               sent = priv->SendCtl[ctx].skb;
+               priv->stats.tx_bytes += sent->len;
+-              dlioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
++              dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
+                               IOC_AND_NETDEV_NAMES_s_s(dev),
+                               __FUNCTION__, sent));
+@@ -722,7 +720,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
+       int ctx;
+       u16 cur_naa = 0x1000;
+-      dlioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n",
++      dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n",
+                       __FUNCTION__, skb));
+       spin_lock_irqsave(&priv->txfidx_lock, flags);
+@@ -748,7 +746,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
+       ctx = priv->mpt_txfidx[priv->mpt_txfidx_tail--];
+       spin_unlock_irqrestore(&priv->txfidx_lock, flags);
+-//    dlioprintk((KERN_INFO MYNAM ": %s/%s: Creating new msg frame (send).\n",
++//    dioprintk((KERN_INFO MYNAM ": %s/%s: Creating new msg frame (send).\n",
+ //                    IOC_AND_NETDEV_NAMES_s_s(dev)));
+       pSendReq = (LANSendRequest_t *) mf;
+@@ -783,7 +781,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
+       pTrans->Flags         = 0;
+       pTrans->TransactionContext[0] = cpu_to_le32(ctx);
+-//    dlioprintk((KERN_INFO MYNAM ": %s/%s: BC = %08x, skb = %p, buff = %p\n",
++//    dioprintk((KERN_INFO MYNAM ": %s/%s: BC = %08x, skb = %p, buff = %p\n",
+ //                    IOC_AND_NETDEV_NAMES_s_s(dev),
+ //                    ctx, skb, skb->data));
+@@ -843,7 +841,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
+       mpt_put_msg_frame (LanCtx, mpt_dev, mf);
+       dev->trans_start = jiffies;
+-      dlioprintk((KERN_INFO MYNAM ": %s/%s: Sending packet. FlagsLength = %08x.\n",
++      dioprintk((KERN_INFO MYNAM ": %s/%s: Sending packet. FlagsLength = %08x.\n",
+                       IOC_AND_NETDEV_NAMES_s_s(dev),
+                       le32_to_cpu(pSimple->FlagsLength)));
+@@ -864,10 +862,10 @@ mpt_lan_wake_post_buckets_task(struct ne
+                       schedule_work(&priv->post_buckets_task);
+               } else {
+                       schedule_delayed_work(&priv->post_buckets_task, 1);
+-                      dlioprintk((KERN_INFO MYNAM ": post_buckets queued on "
++                      dioprintk((KERN_INFO MYNAM ": post_buckets queued on "
+                                  "timer.\n"));
+               }
+-              dlioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n",
++              dioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n",
+                          IOC_AND_NETDEV_NAMES_s_s(dev) ));
+       }
+ }
+@@ -880,7 +878,7 @@ mpt_lan_receive_skb(struct net_device *d
+       skb->protocol = mpt_lan_type_trans(skb, dev);
+-      dlioprintk((KERN_INFO MYNAM ": %s/%s: Incoming packet (%d bytes) "
++      dioprintk((KERN_INFO MYNAM ": %s/%s: Incoming packet (%d bytes) "
+                "delivered to upper level.\n",
+                       IOC_AND_NETDEV_NAMES_s_s(dev), skb->len));
+@@ -890,13 +888,13 @@ mpt_lan_receive_skb(struct net_device *d
+       skb->dev = dev;
+       netif_rx(skb);
+-      dlioprintk((MYNAM "/receive_skb: %d buckets remaining\n",
++      dioprintk((MYNAM "/receive_skb: %d buckets remaining\n",
+                atomic_read(&priv->buckets_out)));
+       if (atomic_read(&priv->buckets_out) < priv->bucketthresh)
+               mpt_lan_wake_post_buckets_task(dev, 1);
+-      dlioprintk((KERN_INFO MYNAM "/receive_post_reply: %d buckets "
++      dioprintk((KERN_INFO MYNAM "/receive_post_reply: %d buckets "
+                 "remaining, %d received back since sod\n",
+                 atomic_read(&priv->buckets_out), priv->total_received));
+@@ -1027,8 +1025,8 @@ mpt_lan_receive_post_reply(struct net_de
+       int count;
+       int i, l;
+-      dlioprintk((KERN_INFO MYNAM ": mpt_lan_receive_post_reply called\n"));
+-      dlioprintk((KERN_INFO MYNAM ": receive_post_reply: IOCStatus: %04x\n",
++      dioprintk((KERN_INFO MYNAM ": mpt_lan_receive_post_reply called\n"));
++      dioprintk((KERN_INFO MYNAM ": receive_post_reply: IOCStatus: %04x\n",
+                le16_to_cpu(pRecvRep->IOCStatus)));
+       if ((le16_to_cpu(pRecvRep->IOCStatus) & MPI_IOCSTATUS_MASK) ==
+@@ -1057,14 +1055,14 @@ mpt_lan_receive_post_reply(struct net_de
+ //                            offset);
+ //    }
+-      dlioprintk((KERN_INFO MYNAM ": %s/%s: @rpr, offset = %d, len = %d\n",
++      dioprintk((KERN_INFO MYNAM ": %s/%s: @rpr, offset = %d, len = %d\n",
+                       IOC_AND_NETDEV_NAMES_s_s(dev),
+                       offset, len));
+       if (count > 1) {
+               int szrem = len;
+-//            dlioprintk((KERN_INFO MYNAM ": %s/%s: Multiple buckets returned "
++//            dioprintk((KERN_INFO MYNAM ": %s/%s: Multiple buckets returned "
+ //                    "for single packet, concatenating...\n",
+ //                            IOC_AND_NETDEV_NAMES_s_s(dev)));
+@@ -1086,7 +1084,7 @@ mpt_lan_receive_post_reply(struct net_de
+                       if (szrem < l)
+                               l = szrem;
+-//                    dlioprintk((KERN_INFO MYNAM ": %s/%s: Buckets = %d, len = %u\n",
++//                    dioprintk((KERN_INFO MYNAM ": %s/%s: Buckets = %d, len = %u\n",
+ //                                    IOC_AND_NETDEV_NAMES_s_s(dev),
+ //                                    i, l));
+@@ -1214,7 +1212,7 @@ mpt_lan_post_receive_buckets(void *dev_i
+       curr = atomic_read(&priv->buckets_out);
+       buckets = (priv->max_buckets_out - curr);
+-      dlioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n",
++      dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n",
+                       IOC_AND_NETDEV_NAMES_s_s(dev),
+                       __FUNCTION__, buckets, curr));
+@@ -1226,7 +1224,7 @@ mpt_lan_post_receive_buckets(void *dev_i
+               if (mf == NULL) {
+                       printk (KERN_ERR "%s: Unable to alloc request frame\n",
+                               __FUNCTION__);
+-                      dlioprintk((KERN_ERR "%s: %u buckets remaining\n",
++                      dioprintk((KERN_ERR "%s: %u buckets remaining\n",
+                                __FUNCTION__, buckets));
+                       goto out;
+               }
+@@ -1337,9 +1335,9 @@ mpt_lan_post_receive_buckets(void *dev_i
+       }
+ out:
+-      dlioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n",
++      dioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n",
+                 __FUNCTION__, buckets, atomic_read(&priv->buckets_out)));
+-      dlioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n",
++      dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n",
+       __FUNCTION__, priv->total_posted, priv->total_received));
+       clear_bit(0, &priv->post_buckets_active);
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.h linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.h 2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.h        2007-11-02 09:10:23.000000000 +0100
+@@ -65,9 +65,9 @@ MODULE_DESCRIPTION(LANAME);
+ /*****************************************************************************/
+ #ifdef MPT_LAN_IO_DEBUG
+-#define dlioprintk(x)  printk x
++#define dioprintk(x)  printk x
+ #else
+-#define dlioprintk(x)
++#define dioprintk(x)
+ #endif
+ #ifdef MPT_LAN_DEBUG
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.c linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.c 2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.c        2007-11-02 09:10:23.000000000 +0100
+@@ -3,8 +3,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -64,7 +64,6 @@
+ #include "mptbase.h"
+ #include "mptscsih.h"
+-#include "mptsas.h"
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ #define my_NAME               "Fusion MPT SAS Host driver"
+@@ -74,10 +73,8 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ /* Command line args */
+-
+ static int mpt_pq_filter = 0;
+ module_param(mpt_pq_filter, int, 0);
+ MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
+@@ -90,627 +87,40 @@ static int mpt_sas_hot_plug_enable = 1;
+ module_param(mpt_sas_hot_plug_enable, int, 0);
+ MODULE_PARM_DESC(mpt_sas_hot_plug_enable, " Enable SAS Hot Plug Support: enable=1 (default=1)");
+-static int mpt_cmd_retry_count = 144;
+-module_param(mpt_cmd_retry_count, int, 0);
+-MODULE_PARM_DESC(mpt_cmd_retry_count, " Device discovery TUR command retry count: default=144");
+-
+-extern int mpt_enable_deadioc_detect;
+-
+-extern int    mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 bus, u8 id, u8 lun, int ctx2abort, ulong timeout);
++extern int    mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+ static int    mptsasDoneCtx = -1;
+ static int    mptsasTaskCtx = -1;
+ static int    mptsasInternalCtx = -1; /* Used only for internal commands */
+-static void mptsas_hotplug_work(void *arg);
+-
+-#if defined(CPQ_CIM)
+-/**
+- * mptsas_sas_io_unit_pg0
+- *
+- * obtaining SAS_IO_UNIT page 0
+- *
+- * @ioc
+- * @port_info
+- *
+- **/
+-static int
+-mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
+-{
+-      ConfigExtendedPageHeader_t hdr;
+-      CONFIGPARMS cfg;
+-      SasIOUnitPage0_t *buffer;
+-      dma_addr_t dma_handle;
+-      int error, i;
+-
+-      hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 0;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.pageAddr = 0;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = 10;
+-
+-      error = mpt_config(ioc, &cfg);
+-      if (error)
+-              goto out;
+-      if (!hdr.ExtPageLength) {
+-              error = -ENXIO;
+-              goto out;
+-      }
+-
+-      buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-                                          &dma_handle);
+-      if (!buffer) {
+-              error = -ENOMEM;
+-              goto out;
+-      }
+-
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      error = mpt_config(ioc, &cfg);
+-      if (error)
+-              goto out_free_consistent;
+-
+-      port_info->num_phys = buffer->NumPhys;
+-      port_info->phy_info = kmalloc(port_info->num_phys *
+-              sizeof(*port_info->phy_info),GFP_KERNEL);
+-      if (!port_info->phy_info) {
+-              error = -ENOMEM;
+-              goto out_free_consistent;
+-      }
+-
+-      if (port_info->num_phys)
+-              port_info->handle =
+-                  le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
+-      for (i = 0; i < port_info->num_phys; i++) {
+-              port_info->phy_info[i].phy_id = i;
+-              port_info->phy_info[i].port_id =
+-                  buffer->PhyData[i].Port;
+-              port_info->phy_info[i].negotiated_link_rate =
+-                  buffer->PhyData[i].NegotiatedLinkRate;
+-              port_info->phy_info[i].portinfo = port_info;
+-              port_info->phy_info[i].port_flags =
+-                  buffer->PhyData[i].PortFlags;
+-      }
+-
+- out_free_consistent:
+-      pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-                          buffer, dma_handle);
+- out:
+-      return error;
+-}
+-
+-/**
+- * mptsas_sas_device_pg0
+- *
+- * obtaining SAS_DEVICE page 0
+- *
+- * @ioc
+- * device_info
+- *
+- **/
+-static int
+-mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
+-              u32 form, u32 form_specific)
+-{
+-      ConfigExtendedPageHeader_t hdr;
+-      CONFIGPARMS cfg;
+-      SasDevicePage0_t *buffer;
+-      dma_addr_t dma_handle;
+-      u64 sas_address;
+-      int error=0;
+-
+-      hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
+-      hdr.ExtPageLength = 0;
+-      hdr.PageNumber = 0;
+-      hdr.Reserved1 = 0;
+-      hdr.Reserved2 = 0;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+-      hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+-
+-      cfg.cfghdr.ehdr = &hdr;
+-      cfg.pageAddr = form + form_specific;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.dir = 0;    /* read */
+-      cfg.timeout = 10;
+-
+-      memset(device_info, 0, sizeof(struct mptsas_devinfo));
+-      error = mpt_config(ioc, &cfg);
+-      if (error)
+-              goto out;
+-      if (!hdr.ExtPageLength) {
+-              error = -ENXIO;
+-              goto out;
+-      }
+-
+-      buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-                                    &dma_handle);
+-      if (!buffer) {
+-              error = -ENOMEM;
+-              goto out;
+-      }
+-
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      error = mpt_config(ioc, &cfg);
+-      if (error)
+-              goto out_free_consistent;
+-
+-      device_info->handle = le16_to_cpu(buffer->DevHandle);
+-      device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
+-      device_info->handle_enclosure =
+-          le16_to_cpu(buffer->EnclosureHandle);
+-      device_info->slot = le16_to_cpu(buffer->Slot);
+-      device_info->phy_id = buffer->PhyNum;
+-      device_info->port_id = buffer->PhysicalPort;
+-      device_info->id = buffer->TargetID;
+-      device_info->channel = buffer->Bus;
+-      memcpy(&sas_address, &buffer->SASAddress, sizeof(u64));
+-      device_info->sas_address = le64_to_cpu(sas_address);
+-      device_info->device_info =
+-          le32_to_cpu(buffer->DeviceInfo);
+-
+- out_free_consistent:
+-      pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+-                          buffer, dma_handle);
+- out:
+-      return error;
+-}
+-
+-/**
+- *    mptsas_get_number_hotspares - returns num hot spares in this ioc
+- *    @ioc: Pointer to MPT_ADAPTER structure
+- *
+- *    Return: number of hotspares
+- *
+- **/
+-static int
+-mptsas_get_number_hotspares(MPT_ADAPTER *ioc)
+-{
+-      ConfigPageHeader_t       hdr;
+-      CONFIGPARMS              cfg;
+-      IOCPage5_t               *buffer = NULL;
+-      dma_addr_t               dma_handle;
+-      int                      data_sz=0;
+-      int                      rc;
+-
+-      memset(&hdr, 0, sizeof(ConfigPageHeader_t));
+-      memset(&cfg, 0, sizeof(CONFIGPARMS));
+-
+-      rc = 0;
+-      hdr.PageNumber = 5;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-      cfg.cfghdr.hdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.timeout = 10;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto get_ioc_pg5;
+-
+-      if (hdr.PageLength == 0)
+-              goto get_ioc_pg5;
+-
+-      data_sz = hdr.PageLength * 4;
+-      buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
+-              data_sz, &dma_handle);
+-      if (!buffer)
+-              goto get_ioc_pg5;
+-
+-      memset((u8 *)buffer, 0, data_sz);
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto get_ioc_pg5;
+-
+-      rc = buffer->NumHotSpares;
+-
+- get_ioc_pg5:
+-
+-      if (buffer)
+-              pci_free_consistent(ioc->pcidev, data_sz,
+-                  (u8 *) buffer, dma_handle);
+-
+-      return rc;
+-}
+-
+-/**
+- *    mptsas_get_ioc_pg5 - ioc Page 5 hot spares
+- *    @ioc: Pointer to MPT_ADAPTER structure
+- *    @pIocPage5: ioc page 5
+- *
+- *    Return: 0 for success
+- *    -ENOMEM if no memory available
+- *            -EPERM if not allowed due to ISR context
+- *            -EAGAIN if no msg frames currently available
+- *            -EFAULT for non-successful reply or no reply (timeout)
+- **/
+-static int
+-mptsas_get_ioc_pg5(MPT_ADAPTER *ioc, IOCPage5_t *iocPage5)
+-{
+-      ConfigPageHeader_t       hdr;
+-      CONFIGPARMS              cfg;
+-      IOCPage5_t               *buffer = NULL;
+-      dma_addr_t               dma_handle;
+-      int                      data_sz=0;
+-      int                      rc;
+-
+-      memset(&hdr, 0, sizeof(ConfigPageHeader_t));
+-      memset(&cfg, 0, sizeof(CONFIGPARMS));
+-
+-      rc = 0;
+-      hdr.PageNumber = 5;
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
+-      cfg.cfghdr.hdr = &hdr;
+-      cfg.physAddr = -1;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-      cfg.timeout = 10;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto get_ioc_pg5;
+-
+-      if (hdr.PageLength == 0) {
+-              rc = -EFAULT;
+-              goto get_ioc_pg5;
+-      }
+-
+-      data_sz = hdr.PageLength * 4;
+-      buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
+-              data_sz, &dma_handle);
+-      if (!buffer) {
+-              rc = -ENOMEM;
+-              goto get_ioc_pg5;
+-      }
+-
+-      memset((u8 *)buffer, 0, data_sz);
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if ((rc = mpt_config(ioc, &cfg)) != 0)
+-              goto get_ioc_pg5;
+-
+-      memcpy(iocPage5, buffer, sizeof(*iocPage5));
+-
+- get_ioc_pg5:
+-
+-      if (buffer)
+-              pci_free_consistent(ioc->pcidev, data_sz,
+-                  (u8 *) buffer, dma_handle);
+-
+-      return rc;
+-}
+-
+-/**
+- * mptsas_add_device_component
+- *
+- * @ioc
+- * @channel - fw mapped id's
+- * @id
+- * @sas_address
+- * @device_info
+- *
+- **/
+-static void
+-mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
+-      u64 sas_address, u32 device_info)
+-{
+-      struct sas_device_info  *sas_info, *next;
+-
+-      down(&ioc->sas_device_info_mutex);
+-
+-      /*
+-       * Delete all matching sas_address's out of tree
+-       */
+-      list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list) {
+-              if (sas_info->sas_address != sas_address)
+-                      continue;
+-              list_del(&sas_info->list);
+-              kfree(sas_info);
+-      }
+-
+-      /*
+-       * If there is a matching channel/id, then swap out with new target info
+-       */
+-      list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
+-              if (sas_info->fw.channel == channel && sas_info->fw.id == id)
+-                      goto initialize_data;
+-      }
+-
+-      if (!(sas_info = kmalloc(sizeof(*sas_info), GFP_KERNEL)))
+-              goto out;
+-      memset(sas_info, 0, sizeof(*sas_info));
+-
+-      /*
+-       * mapping - is for compatibility with drivers supporting sas transport layer
+-       */
+-      sas_info->fw.id = id;
+-      sas_info->fw.channel = channel;
+-      sas_info->os.id = id;
+-      sas_info->os.channel = channel;
+-      list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
+-
+- initialize_data:
+-
+-      sas_info->sas_address = sas_address;
+-      sas_info->device_info = device_info;
+-      sas_info->is_cached = 0;
+-      sas_info->is_logical_volume = 0;
+-      devtprintk((KERN_INFO "%s: adding channel=%d id=%d "
+-          "sas_address=0x%llX\n", __FUNCTION__, channel, id, sas_address));
+-
+- out:
+-      up(&ioc->sas_device_info_mutex);
+-      return;
+-}
+-
+-/**
+- * mptsas_add_device_component_single
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static void
+-mptsas_add_device_component_single(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-      struct mptsas_devinfo sas_device;
+-      int rc;
+-
+-      rc = mptsas_sas_device_pg0(ioc, &sas_device,
+-          (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+-           MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+-          (channel << 8) + id);
+-      if (rc)
+-              return;
+-
+-      mptsas_add_device_component(ioc, sas_device.channel,
+-          sas_device.id, sas_device.sas_address, sas_device.device_info);
+-}
+-
+-/**
+- * mptsas_add_device_component_hotspare
+- *
+- * Handle adding hotspares into the list
+- *
+- * @ioc
+- *
+- **/
+-static void
+-mptsas_add_device_component_hotspare(MPT_ADAPTER *ioc)
+-{
+-      int             num_hotspares;
+-      IOCPage5_t      *iocPage5;
+-      RaidPhysDiskPage0_t     phys_disk;
+-      int             i;
+-
+-      iocPage5 = NULL;
+-      num_hotspares = mptsas_get_number_hotspares(ioc);
+-      if (!num_hotspares)
+-              goto out;
+-
+-      iocPage5 = kmalloc(offsetof(IOCPage5_t,HotSpare) +
+-          num_hotspares * sizeof(IOC_5_HOT_SPARE), GFP_KERNEL);
+-      if (!iocPage5)
+-              goto out;
+-      memset(iocPage5, 0, sizeof(*iocPage5));
+-      if (mptsas_get_ioc_pg5(ioc, iocPage5) != 0)
+-              goto out;
+-      for(i = 0; i < num_hotspares; i++) {
+-              mpt_raid_phys_disk_pg0(ioc,
+-                  iocPage5->HotSpare[i].PhysDiskNum, &phys_disk );
+-              mptsas_add_device_component_single(ioc,
+-                  phys_disk.PhysDiskBus, phys_disk.PhysDiskID);
+-      }
+- out:
+-      kfree(iocPage5);
+-
+-}
+-
+-/**
+- * mptsas_add_device_component_ir
+- *
+- * Handle Integrated RAID, adding each individual device to list
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static void
+-mptsas_add_device_component_ir(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-      CONFIGPARMS                     cfg;
+-      ConfigPageHeader_t              hdr;
+-      dma_addr_t                      dma_handle;
+-      pRaidVolumePage0_t              buffer = NULL;
+-      int                             i;
+-      RaidPhysDiskPage0_t             phys_disk;
+-      struct sas_device_info          *sas_info;
+-
+-      memset(&cfg, 0 , sizeof(CONFIGPARMS));
+-      memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+-      hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+-      cfg.pageAddr = (channel << 8) + id;
+-      cfg.cfghdr.hdr = &hdr;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+-
+-      if (mpt_config(ioc, &cfg) != 0)
+-              goto out;
+-
+-      if (!hdr.PageLength)
+-              goto out;
+-
+-      buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+-          &dma_handle);
+-
+-      if (!buffer)
+-              goto out;
+-
+-      cfg.physAddr = dma_handle;
+-      cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+-
+-      if (mpt_config(ioc, &cfg) != 0)
+-              goto out;
+-
+-      if (!buffer->NumPhysDisks)
+-              goto out;
+-
+-      /*
+-       * Adding entry for hidden components
+-       */
+-      for (i = 0; i < buffer->NumPhysDisks; i++) {
+-
+-              if(mpt_raid_phys_disk_pg0(ioc,
+-                  buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+-                      continue;
+-              mptsas_add_device_component_single(ioc, phys_disk.PhysDiskBus,
+-                  phys_disk.PhysDiskID);
+-      }
+-
+-      /*
+-       * Adding entry for logical volume in list
+-       */
+-      list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
+-              if (sas_info->fw.channel == channel && sas_info->fw.id ==  id)
+-                      goto initialize_data;
+-      }
+-
+-      if (!(sas_info = kmalloc(sizeof(*sas_info), GFP_KERNEL)))
+-              goto out;
+-      memset(sas_info, 0, sizeof(*sas_info));
+-
+-      sas_info->fw.id = id;
+-      sas_info->fw.channel = channel; /* channel zero */
+-      down(&ioc->sas_device_info_mutex);
+-      list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
+-      up(&ioc->sas_device_info_mutex);
+-
+- initialize_data:
+-
+-      sas_info->os.id = id;
+-      sas_info->os.channel = channel;
+-      sas_info->sas_address = 0;
+-      sas_info->device_info = 0;
+-      sas_info->is_logical_volume = 1;
+-      sas_info->is_cached = 0;
+-
+-      devtprintk((KERN_INFO "%s: adding volume at channel=%d id=%d\n",
+-          __FUNCTION__, channel, id));
+-
+-      mptsas_add_device_component_hotspare(ioc);
+- out:
+-      if (buffer)
+-              pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+-                  dma_handle);
+-}
+-
+-
+-/**
+- * mptsas_del_device_component
+- *
+- * Once a device has been removed, we mark the
+- * entry in the list as being cached
+- *
+- * @ioc
+- * @channel - os mapped id's
+- * @id
+- *
+- **/
+-static void
+-mptsas_del_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-      struct sas_device_info  *sas_info, *next;
+-
+-      /*
+-       * Set is_cached flag
+-       */
+-      list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list) {
+-              if (sas_info->os.channel == channel && sas_info->os.id == id) {
+-                      sas_info->is_cached = 1;
+-                      devtprintk((KERN_INFO
+-                          "%s: deleting channel=%d id=%d "
+-                          "sas_address=0x%llX\n", __FUNCTION__, channel, id,
+-                          sas_info->sas_address));
+-              }
+-      }
+-}
+-
+-/**
+- * mptsas_del_device_components
+- *
+- * Cleaning the list
+- *
+- * @ioc
+- *
+- **/
+-static void
+-mptsas_del_device_components(MPT_ADAPTER *ioc)
+-{
+-      struct sas_device_info  *sas_info, *next;
+-
+-      down(&ioc->sas_device_info_mutex);
+-      list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list) {
+-              list_del(&sas_info->list);
+-              kfree(sas_info);
+-      }
+-      up(&ioc->sas_device_info_mutex);
+-}
+-#endif
+-
+-/**
+- * mptsas_find_vdevice
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- **/
+-static VirtDevice *
+-mptsas_find_vdevice(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-      struct _MPT_DEVICE *pMptTarget;
+-
+-      if (id >= ioc->DevicesPerBus || channel >= ioc->NumberOfBuses)
+-              return NULL;
++enum mptsas_hotplug_action {
++      MPTSAS_ADD_DEVICE,
++      MPTSAS_DEL_DEVICE,
++};
+-      pMptTarget = ioc->Target_List[channel];
+-      return pMptTarget->Target[id];
+-}
++struct mptsas_hotplug_event {
++      struct work_struct      work;
++      MPT_ADAPTER             *ioc;
++      enum mptsas_hotplug_action event_type;
++      u64                     sas_address;
++      u32                     channel;
++      u32                     id;
++      u32                     device_info;
++      u16                     handle;
++      u16                     parent_handle;
++      u8                      phy_id;
++      u8                      isRaid;
++};
+-/**
+- * mptsas_qcmd
+- *
+- * receiving a scsi_cmnd from upper layers
+- *
+- * @SCpnt
+- * @done
+- *
+- **/
+ static int
+ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+ {
+       MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+-      MPT_ADAPTER *ioc = hd->ioc;
+-      static VirtDevice *pTarget;
+-      int id = SCpnt->device->id;
+-      int channel = SCpnt->device->channel;
+-
+-      /* If Device has been removed, inhibit any more IO */
+-      pTarget = mptsas_find_vdevice(ioc, channel, id);
+-      if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_DELETED)) {
++      int      id = SCpnt->device->id;
++
++      /* Device has been removed, so inhibit any more IO */
++      if (hd->Targets[id] &&
++          hd->Targets[id]->tflags & MPT_TARGET_FLAGS_DELETED) {
+               SCpnt->result = DID_NO_CONNECT << 16;
+               done(SCpnt);
+               return 0;
+@@ -719,32 +129,6 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, voi
+       return mptscsih_qcmd(SCpnt,done);
+ }
+-/**
+- * mptsas_slave_configure
+- *
+- *
+- * @sdev
+- *
+- **/
+-static int
+-mptsas_slave_configure(struct scsi_device *sdev)
+-{
+-#if defined(CPQ_CIM)
+-      MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+-      MPT_ADAPTER *ioc = hd->ioc;
+-      int             channel;
+-      int             id;
+-
+-      channel = sdev->channel;
+-      id = sdev->id;
+-
+-      if ((ioc->raid_data.isRaid & (1 << id)) == 0)
+-              mptsas_add_device_component_single(ioc, channel, id);
+-#endif
+-      return mptscsih_slave_configure(sdev);
+-}
+-
+-
+ /* Show the ioc state for this card */
+ static ssize_t
+ mptsas_show_iocstate(struct class_device *class_dev, char *buf)
+@@ -778,300 +162,49 @@ static struct scsi_host_template mptsas_
+       .info                           = mptscsih_info,
+       .queuecommand                   = mptsas_qcmd,
+       .slave_alloc                    = mptscsih_slave_alloc,
+-      .slave_configure                = mptsas_slave_configure,
+-      .slave_destroy                  = mptscsih_slave_destroy,
+-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11))
+-      .change_queue_depth             = mptscsih_change_queue_depth,
+-#endif
+-      .eh_abort_handler               = mptscsih_abort,
+-      .eh_device_reset_handler        = mptscsih_dev_reset,
+-      .eh_bus_reset_handler           = mptscsih_bus_reset,
+-      .eh_host_reset_handler          = mptscsih_host_reset,
+-      .bios_param                     = mptscsih_bios_param,
+-      .can_queue                      = MPT_FC_CAN_QUEUE,
+-      .this_id                        = -1,
+-      .sg_tablesize                   = CONFIG_FUSION_MAX_SGE,
+-      .max_sectors                    = 8192,
+-      .cmd_per_lun                    = 7,
+-      .use_clustering                 = ENABLE_CLUSTERING,
+-      .shost_attrs                    = mptsas_host_attrs,
+-      .dump_sanity_check              = mptscsih_sanity_check,
+-      .dump_poll                      = mptscsih_poll,
+-};
+-
+-/**
+- * mptsas_remove
+- *
+- *
+- * @pdev
+- *
+- **/
+-static void __devexit mptsas_remove(struct pci_dev *pdev)
+-{
+-#if defined(CPQ_CIM)
+-      MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+-  if(ioc->sh != NULL)
+-      mptsas_del_device_components(ioc);
+-#endif
+-
+-      flush_scheduled_work();
+-      mptscsih_remove(pdev);
+-}
+-
+-/**
+- * mptsas_target_reset
+- *
+- * Issues TARGET_RESET to end device using handshaking method
+- *
+- * @ioc
+- * @channel
+- * @id
+- *
+- * Returns (1) success
+- *         (0) failure
+- *
+- **/
+-static int
+-mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
+-{
+-      MPT_FRAME_HDR   *mf;
+-      SCSITaskMgmt_t  *pScsiTm;
+-
+-      if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
+-              dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
+-                  ioc->name,__FUNCTION__, __LINE__));
+-              return 0;
+-      }
+-
+-      /* Format the Request
+-       */
+-      pScsiTm = (SCSITaskMgmt_t *) mf;
+-      memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
+-      pScsiTm->TargetID = id;
+-      pScsiTm->Bus = channel;
+-      pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+-      pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+-      pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
+-
+-// EDM        printk("tm target reset : issue : channel=%d id=%d\n", channel, id);
+-      DBG_DUMP_TM_REQUEST_FRAME(mf);
+-
+-      if (mpt_send_handshake_request(ioc->TaskCtx, ioc,
+-          sizeof(SCSITaskMgmt_t), (u32 *)mf, 10,NO_SLEEP)) {
+-              mpt_free_msg_frame(ioc, mf);
+-              dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n",
+-                  ioc->name,__FUNCTION__, __LINE__));
+-              return 0;
+-      }
+-
+-      return 1;
+-}
+-
+-/**
+- * mptsas_target_reset_queue
+- *
+- * Receive request for TARGET_RESET after recieving an firmware
+- * event NOT_RESPONDING_EVENT, then put command in link list
+- * and queue if task_queue already in use.
+- *
+- * @ioc
+- * @sas_event_data
+- *
+- **/
+-static void
+-mptsas_target_reset_queue(MPT_ADAPTER *ioc,
+-    EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+-{
+-      MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+-      VirtDevice *vdevice = NULL;
+-      struct mptscsih_target_reset    *target_reset_list;
+-      u8              id, channel;
+-
+-      id = sas_event_data->TargetID;
+-      channel = sas_event_data->Bus;
+-
+-      if (!(vdevice = mptsas_find_vdevice(ioc, channel, id)))
+-              return;
+-
+-      vdevice->tflags |= MPT_TARGET_FLAGS_DELETED;
+-
+-      target_reset_list = kmalloc(sizeof(*target_reset_list),
+-          GFP_ATOMIC);
+-      if (!target_reset_list) {
+-              dfailprintk((MYIOC_s_WARN_FMT
+-                      "%s, failed to allocate mem @%d..!!\n",
+-                  ioc->name,__FUNCTION__, __LINE__));
+-              return;
+-      }
+-
+-      memset(target_reset_list, 0, sizeof(*target_reset_list));
+-// EDM        printk("tm target reset : queue : channel=%d id=%d\n", channel, id);
+-
+-      memcpy(&target_reset_list->sas_event_data, sas_event_data,
+-              sizeof(*sas_event_data));
+-      list_add_tail(&target_reset_list->list, &hd->target_reset_list);
+-
+-      if (hd->resetPending)
+-              return;
+-
+-      if (mptsas_target_reset(ioc, channel, id)) {
+-              target_reset_list->target_reset_issued = 1;
+-              hd->resetPending = 1;
+-      }
+-}
+-
+-/**
+- * mptsas_dev_reset_complete
+- *
+- * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
+- * enable work queue to finish off removing device from upper layers.
+- * then send next TARGET_RESET in the queue.
+- *
+- * @ioc
+- *
+- **/
+-static void
+-mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
+-{
+-      MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+-        struct list_head *head = &hd->target_reset_list;
+-      struct mptscsih_target_reset    *target_reset_list;
+-      struct mptsas_hotplug_event *ev;
+-      EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
+-      u8              id, channel;
+-      u64             sas_address;
+-
+-      if (list_empty(head))
+-              return;
+-
+-      target_reset_list = list_entry(head->next,
+-          struct mptscsih_target_reset, list);
+-
+-      sas_event_data = &target_reset_list->sas_event_data;
+-      id = sas_event_data->TargetID;
+-      channel = sas_event_data->Bus;
+-      hd->resetPending = 0;
+-
+-      /*
+-       * retry target reset
+-       */
+-      if (!target_reset_list->target_reset_issued) {
+-              if (mptsas_target_reset(ioc, channel, id)) {
+-                      target_reset_list->target_reset_issued = 1;
+-                      hd->resetPending = 1;
+-              }
+-              return;
+-      }
+-
+-// EDM        printk("tm target reset : complete : channel=%d id=%d\n", channel, id);
+-
+-      /*
+-       * enable work queue to remove device from upper layers
+-       */
+-      list_del(&target_reset_list->list);
+-
+-      ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+-      if (!ev) {
+-              dfailprintk((MYIOC_s_WARN_FMT
+-                  "%s, failed to allocate mem @%d..!!\n",
+-                  ioc->name,__FUNCTION__, __LINE__));
+-              return;
+-      }
+-
+-      memset(ev, 0, sizeof(*ev));
+-      INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+-      ev->ioc = ioc;
+-      ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+-      ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
+-      ev->channel = channel;
+-      ev->id = id;
+-      ev->phy_id = sas_event_data->PhyNum;
+-      memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(u64));
+-      ev->sas_address = le64_to_cpu(sas_address);
+-      ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+-      ev->event_type = MPTSAS_DEL_DEVICE;
+-      schedule_work(&ev->work);
+-      kfree(target_reset_list);
+-
+-      /*
+-       * issue target reset to next device in the queue
+-       */
+-
+-      head = &hd->target_reset_list;
+-      if (list_empty(head))
+-              return;
+-
+-      target_reset_list = list_entry(head->next, struct mptscsih_target_reset,
+-          list);
+-
+-      sas_event_data = &target_reset_list->sas_event_data;
+-      id = sas_event_data->TargetID;
+-      channel = sas_event_data->Bus;
+-
+-      if (mptsas_target_reset(ioc, channel, id)) {
+-              target_reset_list->target_reset_issued = 1;
+-              hd->resetPending = 1;
+-      }
+-}
++      .slave_configure                = mptscsih_slave_configure,
++      .slave_destroy                  = mptscsih_slave_destroy,
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11))
++      .change_queue_depth             = mptscsih_change_queue_depth,
++#endif
++      .eh_abort_handler               = mptscsih_abort,
++      .eh_device_reset_handler        = mptscsih_dev_reset,
++      .eh_bus_reset_handler           = mptscsih_bus_reset,
++      .eh_host_reset_handler          = mptscsih_host_reset,
++      .bios_param                     = mptscsih_bios_param,
++      .can_queue                      = MPT_FC_CAN_QUEUE,
++      .this_id                        = -1,
++      .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
++      .max_sectors                    = 8192,
++      .cmd_per_lun                    = 7,
++      .use_clustering                 = ENABLE_CLUSTERING,
++      .shost_attrs                    = mptsas_host_attrs,
++      .dump_sanity_check              = mptscsih_sanity_check,
++      .dump_poll                      = mptscsih_poll,
++};
+-/**
+- * mptsas_taskmgmt_complete
+- *
+- * @ioc
+- * @mf
+- * @mr
+- *
+- **/
+-static int
+-mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
++static void __devexit mptsas_remove(struct pci_dev *pdev)
+ {
+-      mptsas_dev_reset_complete(ioc);
+-      return mptscsih_taskmgmt_complete(ioc, mf, mr);
++      flush_scheduled_work();
++      mptscsih_remove(pdev);
+ }
+-/**
+- * mptscsih_ioc_reset
+- *
+- * @ioc
+- * @reset_phase
+- *
+- **/
+-static int
+-mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
++static void
++mptsas_target_reset(MPT_ADAPTER *ioc, VirtDevice * vdevice)
+ {
+-        MPT_SCSI_HOST   *hd =NULL;
+-      struct mptscsih_target_reset    *target_reset_list, *n;
+-      int rc;
+-
+-        if ((ioc->sh != NULL) && (ioc->sh->hostdata != NULL))
+-              hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+-
+-      rc = mptscsih_ioc_reset(ioc, reset_phase);
++      MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+-      if (reset_phase != MPT_IOC_POST_RESET)
+-              goto out;
+-
+-      if (ioc->bus_type != SAS)
+-              goto out;
+-       if(hd == NULL)
+-               goto out;
+-
+-
+-      if (list_empty(&hd->target_reset_list))
+-              goto out;
+-
+-      /* flush the target_reset_list */
+-      list_for_each_entry_safe(target_reset_list, n,
+-          &hd->target_reset_list, list) {
+-              list_del(&target_reset_list->list);
+-              kfree(target_reset_list);
++      if (mptscsih_TMHandler(hd,
++           MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
++           vdevice->bus_id, vdevice->target_id, 0, 0, 5) < 0) {
++              hd->tmPending = 0;
++              hd->tmState = TM_STATE_NONE;
++              printk(MYIOC_s_WARN_FMT
++             "Error processing TaskMgmt id=%d TARGET_RESET\n",
++                      ioc->name, vdevice->target_id);
+       }
+-
+- out:
+-      return rc;
+ }
+-
+ /****************************************************************************
+  * Supported hardware
+  */
+@@ -1092,13 +225,6 @@ static struct pci_device_id mptsas_pci_t
+ MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
+-/**
+- * mptscsih_sas_persist_clear_table
+- *
+- *
+- * @ioc
+- *
+- **/
+ static void
+ mptscsih_sas_persist_clear_table(void * arg)
+ {
+@@ -1107,52 +233,76 @@ mptscsih_sas_persist_clear_table(void * 
+       mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
+ }
+-/**
+- * mptsas_hotplug_print
+- *
+- *
+- * @ioc
+- * @hot_plug_info
+- * @msg_string
+- *
+- **/
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* mptbase_sas_update_device_list -
++ * This is called from the work queue.
++ * Purpose is to called when a logical volume has been created, deleted,
++ * or status change.
++ * Since in SAS the phydisk can be moved to different location, we will need
++ * to refresh the device list by recreating it.
++ */
++static void
++mptscsih_sas_update_device_list(MPT_ADAPTER *ioc )
++{
++      sas_device_info_t *sasDevice, *pNext;
++
++      /*
++       * Kill everything in the device list, then rediscover
++       */
++      list_for_each_entry_safe(sasDevice, pNext, &ioc->sasDeviceList, list) {
++              list_del(&sasDevice->list);
++              kfree(sasDevice);
++              ioc->alloc_total -= sizeof (sas_device_info_t);
++      }
++
++      if (ioc->sasPhyInfo != NULL) {
++              kfree(ioc->sasPhyInfo);
++              ioc->sasPhyInfo = NULL;
++              ioc->alloc_total -=
++                  ioc->numPhys * sizeof (sas_phy_info_t);
++      }
++      ioc->numPhys = 0;
++
++      /*
++       *  Rescsan list
++       */
++      mpt_sas_get_info(ioc);
++}
++
+ static void
+ mptsas_hotplug_print(MPT_ADAPTER *ioc, struct mptsas_hotplug_event *hot_plug_info,  u32 lun, u8 * msg_string)
+ {
+-      char *ds;
++      char *ds = NULL;
+       u32     id = hot_plug_info->id;
+-      u32     channel = hot_plug_info->channel;
+-      if ( id >= ioc->DevicesPerBus ) {
+-              printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n",
+-                  ioc->name, __FUNCTION__, id, ioc->DevicesPerBus);
++      if ( id > ioc->pfacts->MaxDevices ) {
++              printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++                  ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
+               return;
+       }
+-      if ( channel >= ioc->NumberOfBuses ) {
+-              printk(MYIOC_s_WARN_FMT
+-                  "%s: Invalid channel=%d, NumberOfBuses=%d\n",
+-                  ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses);
+-              return;
++      if (hot_plug_info->isRaid) {
++              printk(MYIOC_s_INFO_FMT
++                  "%s device, channel %d, id %d, lun %d\n",
++                      ioc->name, msg_string,
++                      hot_plug_info->channel,
++                      id, lun);
++      } else {
++              if (hot_plug_info->device_info &
++                  MPI_SAS_DEVICE_INFO_SSP_TARGET)
++                      ds = "sas";
++              if (hot_plug_info->device_info &
++                  MPI_SAS_DEVICE_INFO_STP_TARGET)
++                      ds = "stp";
++              if (hot_plug_info->device_info &
++                  MPI_SAS_DEVICE_INFO_SATA_DEVICE)
++                      ds = "sata";
++              printk(MYIOC_s_INFO_FMT
++                  "%s %s device, channel %d, id %d, lun %d,"
++                  "  phy %d\n", ioc->name, msg_string, ds,
++                  hot_plug_info->channel, id, lun,
++                  hot_plug_info->phy_id);
+       }
+-
+-      if (hot_plug_info->device_info &
+-          MPI_SAS_DEVICE_INFO_SSP_TARGET)
+-              ds = "sas ";
+-      else if (hot_plug_info->device_info &
+-          MPI_SAS_DEVICE_INFO_STP_TARGET)
+-              ds = "stp ";
+-      else if (hot_plug_info->device_info &
+-          MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+-              ds = "sata ";
+-      else
+-              ds = "";
+-
+-      printk(MYIOC_s_INFO_FMT
+-          "%s %sdevice, channel %d, id %d, lun %d,"
+-          "  phy %d\n", ioc->name, msg_string, ds,
+-          channel, id, lun,
+-          hot_plug_info->phy_id);
+ }
+ /*
+@@ -1167,32 +317,20 @@ mptsas_remove_target(MPT_ADAPTER *ioc, s
+       struct Scsi_Host *shost = ioc->sh;
+       unsigned long flags;
+       struct scsi_device *sdev;
+-      static VirtDevice *pTarget;
+       u32 channel, id;
++      MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+       id = hot_plug_info->id;
+-      channel = hot_plug_info->channel;
+-
+-      if ( id >= ioc->DevicesPerBus ) {
+-              printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n",
+-                  ioc->name, __FUNCTION__, id, ioc->DevicesPerBus);
+-              return;
+-      }
+-      if ( channel >= ioc->NumberOfBuses ) {
+-              printk(MYIOC_s_WARN_FMT
+-                  "%s: Invalid channel=%d, NumberOfBuses=%d\n",
+-                  ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses);
++      if ( id > ioc->pfacts->MaxDevices ) {
++              printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++                  ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
+               return;
+       }
+-      pTarget = mptsas_find_vdevice(ioc, channel, id);
+-      if (!pTarget)
+-              return;
+-
+-      pTarget->tflags &= ~MPT_TARGET_FLAGS_TLR_DONE;
+-
++      mptsas_target_reset(ioc, hd->Targets[id]);
++      channel = hot_plug_info->channel;
+       spin_lock_irqsave(shost->host_lock, flags);
+  restart:
+       list_for_each_entry(sdev, &shost->__devices, siblings) {
+@@ -1208,46 +346,26 @@ mptsas_remove_target(MPT_ADAPTER *ioc, s
+       spin_unlock_irqrestore(shost->host_lock, flags);
+ }
+-/**
+- * mptsas_add_device
+- *
+- *
+- * @ioc
+- * @hot_plug_info
+- *
+- **/
+ static void
+ mptsas_add_device(MPT_ADAPTER *ioc, struct mptsas_hotplug_event *hot_plug_info,
+     u32 lun)
+ {
+       u32     channel, id;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
+       struct scsi_device *sdev;
++#else
++        int   error;
++#endif
+       id = hot_plug_info->id;
+-      if ( id >= ioc->DevicesPerBus ) {
+-              printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n",
+-                  ioc->name, __FUNCTION__, id, ioc->DevicesPerBus);
++      if ( id > ioc->pfacts->MaxDevices ) {
++              printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++                  ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
+               return;
+       }
+       channel = hot_plug_info->channel;
+-      if ( channel >= ioc->NumberOfBuses ) {
+-              printk(MYIOC_s_WARN_FMT
+-                  "%s: Invalid channel=%d, NumberOfBuses=%d\n",
+-                  ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses);
+-              return;
+-      }
+-
+-      /*
+-       * avoid adding a device that is already present
+-       */
+-      sdev = scsi_device_lookup(ioc->sh, channel, id, lun);
+-      if (sdev) {
+-              scsi_device_put(sdev);
+-              return;
+-      }
+-
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
+       sdev = scsi_add_device(ioc->sh, channel, id, lun);
+       if (!IS_ERR(sdev))
+@@ -1261,13 +379,6 @@ mptsas_add_device(MPT_ADAPTER *ioc, stru
+ #endif
+ }
+-/**
+- * scsilun_to_int
+- *
+- *
+- * @scsilun
+- *
+- **/
+ static int scsilun_to_int(struct scsi_lun *scsilun)
+ {
+       int i;
+@@ -1298,170 +409,56 @@ mptsas_scan_target(MPT_ADAPTER *ioc, str
+       u32             length, channel, id, lun, num_luns;
+       u8              *data;
+       u32             retries;
+-      int             rc;
++      int             completion_code;
+       id = hot_plug_info->id;
+-      channel = hot_plug_info->channel;
+-      if ( id > ioc->DevicesPerBus ) {
+-              printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n",
+-                  ioc->name, __FUNCTION__, id, ioc->DevicesPerBus);
+-              return;
+-      }
+-
+-      if ( channel >= ioc->NumberOfBuses ) {
+-              printk(MYIOC_s_WARN_FMT
+-                  "%s: Invalid channel=%d, NumberOfBuses=%d\n",
+-                  ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses);
+-              return;
+-      }
+-
+-      /*
+-       * Integrated RAID doesn't support REPORT_LUNS, it will timeout
+-       */
+-      if (ioc->raid_data.isRaid & (1 << id)) {
+-              mptsas_add_device(ioc, hot_plug_info, 0);
++      if ( id > ioc->pfacts->MaxDevices ) {
++              printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++                  ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
+               return;
+       }
+-      /* initialize REPORT_LUN params */
++      channel = hot_plug_info->channel;
+       lun = 0;
+-      lun_data_len = 0;
+-      lun_data = NULL;
+-      lunp = NULL;
+       /*
+-       * Test Unit Ready
++       * Integrated RAID doesn't support luns greater than 0
+        */
+-      iocmd.cmd = TEST_UNIT_READY;
+-      iocmd.bus = channel;
+-      iocmd.id = id;
+-      iocmd.lun = lun;
+-      iocmd.flags = 0;
+-      iocmd.data_dma = -1;
+-      iocmd.data = NULL;
+-      iocmd.size = 0;
+-      dinitprintk((MYIOC_s_INFO_FMT "Sending TURs to channel=%d id=%d \n",
+-              ioc->name, channel, id));
+-      for (retries = 0; retries < mpt_cmd_retry_count; retries++) {
+-              if (mptscsih_do_cmd(hd, &iocmd) < 0) {
+-                      dinitprintk((MYIOC_s_INFO_FMT
+-                          "TUR: mptscsih_do_cmd failed\n",
+-                          ioc->name));
+-                      goto tur_done;
+-              }
+-
+-              if (hd->pLocal == NULL) {
+-                      dinitprintk((MYIOC_s_INFO_FMT "TUR: no pLocal\n",
+-                          ioc->name));
+-                      goto tur_done;
+-              }
+-
+-              rc = hd->pLocal->completion;
+-              if (rc == MPT_SCANDV_GOOD) {
+-                      dinitprintk((MYIOC_s_INFO_FMT "TUR: succeeded\n",
+-                          ioc->name));
+-                      goto tur_done;
+-              } else if (rc == MPT_SCANDV_BUSY) {
+-                      dinitprintk((MYIOC_s_INFO_FMT "TUR: BUSY\n",
+-                              ioc->name));
+-                       msleep(1000);  /* sleep 1 second */
+-                      continue;
+-              } else if (rc == MPT_SCANDV_SENSE) {
+-                      u8 skey = hd->pLocal->sense[2] & 0x0F;
+-                      u8 asc = hd->pLocal->sense[12];
+-                      u8 ascq = hd->pLocal->sense[13];
+-                      dinitprintk((MYIOC_s_INFO_FMT
+-                          "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
+-                          ioc->name, skey, asc, ascq));
+-
+-                      if (skey == UNIT_ATTENTION) {
+-                              dinitprintk((MYIOC_s_INFO_FMT
+-                                  "TUR: UNIT ATTENTION\n",
+-                                  ioc->name));
+-                              continue;
+-                      } else if ((skey == NOT_READY) &&
+-                          (asc == 0x04)&&(ascq == 0x01)) {
+-                              dinitprintk((MYIOC_s_INFO_FMT
+-                                  "TUR: Becoming Ready\n",
+-                                  ioc->name));
+-                                    msleep(1000);  /* sleep 1 second */
+-                              continue;
+-                      }
+-              }
++      if (hot_plug_info->isRaid) {
++              mptsas_add_device(ioc, hot_plug_info, lun);
++              return;
+       }
+- tur_done:
+-
+       lun_data_len = (MPT_LAST_LUN + 1) * sizeof(struct scsi_lun);
+       lun_data = pci_alloc_consistent(ioc->pcidev, lun_data_len,
+           &lun_data_dma);
+       if (!lun_data)
+-              goto report_luns_done;
++              goto out;
+-      /*
+-       * Report Luns
+-       */
+       iocmd.cmd = REPORT_LUNS;
+       iocmd.data_dma = lun_data_dma;
+       iocmd.data = (u8 *)lun_data;
+       iocmd.size = lun_data_len;
++      iocmd.bus = channel;
++      iocmd.id = id;
++      iocmd.lun = lun;
+       iocmd.flags = 0;
+       /*
+-       * While loop for 10 sec retrying REPORT_LUNS, this is done
++       * While loop for 3 sec retrying REPORT_LUNS, this is done
+        * because some devices return MPI_SCSI_STATUS_BUSY for several
+        * seconds.
+        */
+-      dinitprintk((MYIOC_s_INFO_FMT
+-         "Sending REPORT_LUNS to channel=%d id=%d \n",
+-          ioc->name, channel, id));
++//    for (retries = 0; retries < 3; retries++) {  /* EDM - TRY 10 */
+       for (retries = 0; retries < 10; retries++) {
+               memset(lun_data, 0, lun_data_len);
+-              if (mptscsih_do_cmd(hd, &iocmd) < 0) {
+-                      dinitprintk((MYIOC_s_INFO_FMT
+-                          "RL: mptscsih_do_cmd failed\n", ioc->name));
+-                      goto report_luns_done;
+-              }
+-
+-              if (hd->pLocal == NULL) {
+-                      dinitprintk((MYIOC_s_INFO_FMT "RL: no pLocal\n",
+-                          ioc->name));
+-                      goto report_luns_done;
+-              }
+-
+-              rc = hd->pLocal->completion;
+-              if (rc == MPT_SCANDV_GOOD) {
+-                      dinitprintk((MYIOC_s_INFO_FMT "RL: succeeded\n",
+-                          ioc->name));
+-                      goto report_luns_done;
+-              } else if (rc == MPT_SCANDV_BUSY) {
+-                      dinitprintk((MYIOC_s_INFO_FMT "RL: BUSY\n", ioc->name));
+-                      msleep(1000);
+-                      continue;
+-              } else if (rc == MPT_SCANDV_SENSE) {
+-                      u8 skey = hd->pLocal->sense[2] & 0x0F;
+-                      u8 asc = hd->pLocal->sense[12];
+-                      u8 ascq = hd->pLocal->sense[13];
+-                      dinitprintk((MYIOC_s_INFO_FMT
+-                          "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name,
+-                          skey, asc, ascq));
+-
+-                      if (skey == UNIT_ATTENTION) {
+-                              dinitprintk((MYIOC_s_INFO_FMT
+-                                 "RL: UNIT ATTENTION\n", ioc->name));
+-                              continue;
+-                      } else if ((skey == NOT_READY) &&
+-                          (asc == 0x04)&&(ascq == 0x01)) {
+-                              dinitprintk((MYIOC_s_INFO_FMT
+-                                  "RL: Becoming Ready\n", ioc->name));
+-                                   msleep(1000);
+-                                     continue;
+-                      }
+-              }
++              completion_code = mptscsih_do_cmd(hd, &iocmd);
++              if (!completion_code)
++                      break;
++              msleep(1000);
+       }
+- report_luns_done:
+       /*
+        * Attaching lun=0
+        */
+@@ -1470,8 +467,6 @@ mptsas_scan_target(MPT_ADAPTER *ioc, str
+       /*
+        * Get the length from the first four bytes of lun_data.
+        */
+-      if (!lun_data)
+-              goto out;
+       data = (u8 *)lun_data;
+       length = ((data[0] << 24) | (data[1] << 16) |
+           (data[2] << 8) | (data[3] << 0));
+@@ -1501,91 +496,93 @@ mptsas_scan_target(MPT_ADAPTER *ioc, str
+                   lun_data_dma);
+ }
+-/**
+- * mptsas_hotplug_work
+- *
+- *
+- * @hot_plug_info
+- *
+- **/
+ static void
+ mptsas_hotplug_work(void *arg)
+ {
+       struct mptsas_hotplug_event *hot_plug_info = arg;
+       MPT_ADAPTER             *ioc = hot_plug_info->ioc;
+-      u32                     id, channel;
++      MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
++      VirtDevice              *pTarget;
++      u32                     id = hot_plug_info->id;
+-      id = hot_plug_info->id;
+-      channel = hot_plug_info->channel;
+       dhotpprintk((MYIOC_s_WARN_FMT "Entering %s for channel=%d id=%d\n",
+-              ioc->name,__FUNCTION__, channel, id));
++              ioc->name,__FUNCTION__, 
++              hot_plug_info->channel, id));
++
++
++      if ( id > ioc->pfacts->MaxDevices ) {
++              printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n",
++                  ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices);
++              return;
++      }
+       down(&ioc->hot_plug_semaphore);
+-      /* If there has been a change to raid, then we need to
+-       * refresh the config raid data
+-       */
+-      if (hot_plug_info->refresh_raid_config_pages)
+-              mpt_findImVolumes(ioc);
++      pTarget = hd->Targets[id];
++      dhotpprintk((MYIOC_s_WARN_FMT "hot_plug_info=%p ioc=%p hd=%p pTarget=%p\n",
++                  ioc->name, hot_plug_info, ioc, hd, pTarget));
+       switch  (hot_plug_info->event_type) {
+       case MPTSAS_DEL_DEVICE:
+-#if defined(CPQ_CIM)
+-              mptsas_del_device_component(ioc, channel, id);
+-              if (hot_plug_info->refresh_raid_config_pages)
+-                      mptsas_add_device_component_hotspare(ioc);
+-#endif
+               dhotpprintk((MYIOC_s_WARN_FMT
+                   "MPTSAS_DEL_DEVICE: channel=%d id=%d\n",
+-                  ioc->name, channel, id));
++                      ioc->name,
++                      hot_plug_info->channel,
++                      id));
++              if (pTarget == NULL) {
++                      dhotpprintk((MYIOC_s_WARN_FMT
++                          "hot_plug id=%d not found in Targets array",
++                              ioc->name,
++                              id));
++                      goto out;
++              }
++              pTarget->tflags &= ~MPT_TARGET_FLAGS_TLR_DONE;
++              pTarget->tflags |= MPT_TARGET_FLAGS_DELETED;
+               mptsas_remove_target(ioc, hot_plug_info);
+               break;
+       case MPTSAS_ADD_DEVICE:
+-#if defined(CPQ_CIM)
+-              if (ioc->raid_data.isRaid & (1 << id))
+-                      mptsas_add_device_component_ir(ioc, channel, id);
+-#endif
+               dhotpprintk((MYIOC_s_WARN_FMT
+                   "MPTSAS_ADD_DEVICE: channel=%d id=%d\n",
+-                  ioc->name, channel, id));
++                      ioc->name,
++                      hot_plug_info->channel,
++                      id));
++              if (pTarget) {
++                      dhotpprintk((MYIOC_s_WARN_FMT
++                          "hot_plug id=%d already in Targets array",
++                              ioc->name,
++                              id));
++                      goto out;
++              }
+               mptsas_scan_target(ioc, hot_plug_info);
+               break;
+-#if defined(CPQ_CIM)
+-      case MPTSAS_ADD_INACTIVE_VOLUME:
+-              dhotpprintk((MYIOC_s_WARN_FMT
+-                  "MPTSAS_ADD_INACTIVE_VOLUME: channel=%d id=%d\n",
+-                  ioc->name, channel, id));
+-              mptsas_add_device_component_ir(ioc, channel, id);
+-              break;
+-      case MPTSAS_PHYSDISK_ADD:
+-              mptsas_add_device_component_single(ioc, channel, id);
+-              break;
+-#endif
+       default:
+               dhotpprintk((MYIOC_s_WARN_FMT
+-                  "Unknown hot_plug event_type=%x: channel=%d id=%d "
+-                  " skipping\n", ioc->name, hot_plug_info->event_type,
+-                  channel, id));
+-              goto out;
++                  "Unknown hot_plug event_type=%x: channel=%d id=%d\n",
++                      ioc->name,
++                      hot_plug_info->event_type,
++                      hot_plug_info->channel,
++                      id));
++              break;
++      }
++
++      /* If there has been a change to raid, then we need to
++       * refresh the config raid data, and sas device link list
++       */
++      if (hot_plug_info->isRaid) {
++              mpt_findImVolumes(ioc);
++              mptscsih_sas_update_device_list(ioc);
+       }
+  out:
+       dhotpprintk((MYIOC_s_WARN_FMT "%s: kfree hot_plug_info=%p\n",
+-          ioc->name,__FUNCTION__, hot_plug_info));
++                  ioc->name,__FUNCTION__, hot_plug_info));
+       kfree(hot_plug_info);
+       up(&ioc->hot_plug_semaphore);
+ }
+-/**
+- * mptsas_send_sas_event
+- *
+- *
+- * @ioc
+- * @sas_event_data
+- *
+- **/
++
+ static void
+ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+               EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+@@ -1610,11 +607,8 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+       }
+       switch (sas_event_data->ReasonCode) {
+-      case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+-              mptsas_target_reset_queue(ioc, sas_event_data);
+-              break;
+-
+       case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
++      case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+               ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+               if (!ev) {
+                       printk(KERN_WARNING "mptsas: lost hotplug event\n");
+@@ -1642,7 +636,6 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+                       ev->event_type = MPTSAS_DEL_DEVICE;
+               schedule_work(&ev->work);
+               break;
+-
+       case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+       /*
+        * Persistent table is full.
+@@ -1652,7 +645,6 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+                   (void *)ioc);
+               schedule_work(&ioc->mptscsih_persistTask);
+               break;
+-
+       case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+       /* TODO */
+       case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
+@@ -1662,21 +654,12 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
+       }
+ }
+-/**
+- * mptsas_send_raid_event
+- *
+- *
+- * @ioc
+- * @raid_event_data
+- *
+- **/
+ static void
+ mptsas_send_raid_event(MPT_ADAPTER *ioc,
+               EVENT_DATA_RAID *raid_event_data)
+ {
+       struct mptsas_hotplug_event *ev;
+-      int status = le32_to_cpu(raid_event_data->SettingsStatus);
+-      int state = (status >> 8) & 0xff;
++      RAID_VOL0_STATUS * volumeStatus;
+       if (ioc->bus_type != SAS)
+               return;
+@@ -1688,13 +671,11 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
+       }
+       memset(ev,0,sizeof(struct mptsas_hotplug_event));
++      INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+       ev->ioc = ioc;
+       ev->id = raid_event_data->VolumeID;
+-      ev->channel = raid_event_data->VolumeBus;
+-      ev->refresh_raid_config_pages = 1;
++      ev->isRaid=1;
+-      devtprintk((KERN_INFO MYNAM ": VolumeID=%d Reason=%x received\n",
+-          ev->id, raid_event_data->ReasonCode));
+       switch (raid_event_data->ReasonCode) {
+       case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+               ev->event_type = MPTSAS_ADD_DEVICE;
+@@ -1702,24 +683,6 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
+       case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
+               ev->event_type = MPTSAS_DEL_DEVICE;
+               break;
+-      case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
+-              switch (state) {
+-              case MPI_PD_STATE_ONLINE:
+-              case MPI_PD_STATE_NOT_COMPATIBLE:
+-                      ev->event_type = MPTSAS_PHYSDISK_ADD;
+-                      break;
+-              case MPI_PD_STATE_MISSING:
+-              case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
+-              case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
+-              case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
+-                      ev->event_type = MPTSAS_DEL_DEVICE;
+-                      break;
+-              default:
+-                      devtprintk((KERN_INFO MYNAM
+-                          ": ignoring this event! %d\n", __LINE__));
+-                      return;
+-              }
+-              break;
+       case MPI_EVENT_RAID_RC_VOLUME_DELETED:
+               ev->event_type = MPTSAS_DEL_DEVICE;
+               break;
+@@ -1727,68 +690,18 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
+               ev->event_type = MPTSAS_ADD_DEVICE;
+               break;
+       case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
+-              switch (state) {
+-              case MPI_RAIDVOL0_STATUS_STATE_FAILED:
+-              case MPI_RAIDVOL0_STATUS_STATE_MISSING:
+-                      ev->event_type = MPTSAS_DEL_DEVICE;
+-                      break;
+-              case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
+-              case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
+-                      ev->event_type = MPTSAS_ADD_DEVICE;
+-                      break;
+-              default:
+-                      devtprintk((KERN_INFO MYNAM
+-                          ": ignoring this event! %d\n", __LINE__));
+-                      return;
+-              }
++              volumeStatus = (RAID_VOL0_STATUS *) &
++                  raid_event_data->SettingsStatus;
++              ev->event_type = (volumeStatus->State ==
++                  MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
++                  MPTSAS_DEL_DEVICE : MPTSAS_ADD_DEVICE;
+               break;
+       default:
+-              devtprintk((KERN_INFO MYNAM
+-                  ": ignoring this event! %d\n", __LINE__));
+-              return;
++              break;
+       }
+-      INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+       schedule_work(&ev->work);
+ }
+-#if defined(CPQ_CIM)
+-/*
+- * mptsas_send_ir2_event
+- *
+- * This handle exposing hidden disk when an inactive raid volume is added
+- */
+-static void
+-mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
+-{
+-      struct mptsas_hotplug_event *ev;
+-
+-      if (ir2_data->ReasonCode !=
+-          MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
+-              return;
+-
+-      ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+-      if (!ev)
+-              return;
+-      memset(ev, 0, sizeof(*ev));
+-      ev->ioc = ioc;
+-      ev->id = ir2_data->TargetID;
+-      ev->channel = ir2_data->Bus;
+-      ev->refresh_raid_config_pages = 1;
+-      ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
+-
+-      INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+-      schedule_work(&ev->work);
+-};
+-#endif
+-
+-/**
+- * mptsas_event_process
+- *
+- *
+- * @ioc
+- * @reply
+- *
+- **/
+ static int
+ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
+ {
+@@ -1803,16 +716,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, E
+       switch (event) {
+       case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+-#if defined(CPQ_CIM)
+-              ioc->csmi_change_count++;
+-#endif
+               mptsas_send_sas_event(ioc,
+                       (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
+               break;
+       case MPI_EVENT_INTEGRATED_RAID:
+-#if defined(CPQ_CIM)
+-              ioc->csmi_change_count++;
+-#endif
+               mptsas_send_raid_event(ioc,
+                       (EVENT_DATA_RAID *)reply->Data);
+               break;
+@@ -1822,13 +729,6 @@ mptsas_event_process(MPT_ADAPTER *ioc, E
+                   (void *)ioc);
+               schedule_work(&ioc->mptscsih_persistTask);
+               break;
+-#if defined(CPQ_CIM)
+-      case MPI_EVENT_IR2:
+-              ioc->csmi_change_count++;
+-              mptsas_send_ir2_event(ioc,
+-                  (PTR_MPI_EVENT_DATA_IR2)reply->Data);
+-              break;
+-#endif
+       default:
+               rc = mptscsih_event_process(ioc, reply);
+               break;
+@@ -1855,13 +755,12 @@ mptsas_probe(struct pci_dev *pdev, const
+       MPT_ADAPTER             *ioc;
+       unsigned long            flags;
+       int                      sz, ii;
++      int                      numSGE = 0;
++      int                      scale;
+       int                      ioc_cap;
+       u8                      *mem;
+       int                     error=0;
+       int                     r;
+-#if defined(CPQ_CIM)
+-      struct mptsas_portinfo  *port_info;
+-#endif
+       if ((r = mpt_attach(pdev,id)) != 0)
+               return r;
+@@ -1874,27 +773,19 @@ mptsas_probe(struct pci_dev *pdev, const
+       /*  Added sanity check on readiness of the MPT adapter.
+        */
+       if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
+-                 if(mpt_enable_deadioc_detect)
+-                   return 0;
+-                 else {
+-                  printk(MYIOC_s_WARN_FMT
+-                         "Skipping because it's not operational!\n", ioc->name);
+-                      error = -ENODEV;
+-               goto out_mptsas_probe;
+-                 }
++              printk(MYIOC_s_WARN_FMT
++                "Skipping because it's not operational!\n",
++                ioc->name);
++              error = -ENODEV;
++              goto out_mptsas_probe;
+       }
+       if (!ioc->active) {
+-            if(mpt_enable_deadioc_detect)
+-                      return 0;
+-               else {
+-
+-              printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
++              printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
+                 ioc->name);
+               error = -ENODEV;
+               goto out_mptsas_probe;
+       }
+-     }
+       /*  Sanity check - ensure at least 1 port is INITIATOR capable
+        */
+@@ -1906,8 +797,9 @@ mptsas_probe(struct pci_dev *pdev, const
+       }
+       if (!ioc_cap) {
+-              printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI "
+-                  "Initiator mode is NOT enabled!\n", ioc->name, ioc);
++              printk(MYIOC_s_WARN_FMT
++                      "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
++                      ioc->name, ioc);
+               return 0;
+       }
+@@ -1915,8 +807,8 @@ mptsas_probe(struct pci_dev *pdev, const
+       if (!sh) {
+               printk(MYIOC_s_WARN_FMT
+-                  "Unable to register controller with SCSI subsystem\n",
+-                  ioc->name);
++                      "Unable to register controller with SCSI subsystem\n",
++                      ioc->name);
+               error = -1;
+               goto out_mptsas_probe;
+         }
+@@ -1939,19 +831,49 @@ mptsas_probe(struct pci_dev *pdev, const
+       else
+               sh->can_queue = ioc->req_depth;
+       dinitprintk((MYIOC_s_INFO_FMT
+-          "mpt_can_queue=%d req_depth=%d can_queue=%d\n",
+-          ioc->name, mpt_can_queue, ioc->req_depth, sh->can_queue));
++              "mpt_can_queue=%d req_depth=%d can_queue=%d\n",
++              ioc->name, mpt_can_queue, ioc->req_depth,
++              sh->can_queue));
+-      sh->max_id = ioc->DevicesPerBus;
++      sh->max_id = ioc->pfacts->MaxDevices + 1;
+       sh->max_lun = MPT_LAST_LUN + 1;
+-      sh->max_channel = ioc->NumberOfBuses - 1;
++      sh->max_channel = 0;
+       sh->this_id = ioc->pfacts[0].PortSCSIID;
+       /* Required entry.
+        */
+       sh->unique_id = ioc->id;
+-      sh->sg_tablesize = ioc->sg_tablesize;
++
++      /* Verify that we won't exceed the maximum
++       * number of chain buffers
++       * We can optimize:  ZZ = req_sz/sizeof(SGE)
++       * For 32bit SGE's:
++       *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
++       *               + (req_sz - 64)/sizeof(SGE)
++       * A slightly different algorithm is required for
++       * 64bit SGEs.
++       */
++      scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
++      if (sizeof(dma_addr_t) == sizeof(u64)) {
++              numSGE = (scale - 1) *
++                (ioc->facts.MaxChainDepth-1) + scale +
++                (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
++                sizeof(u32));
++      } else {
++              numSGE = 1 + (scale - 1) *
++                (ioc->facts.MaxChainDepth-1) + scale +
++                (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
++                sizeof(u32));
++      }
++
++      if (numSGE < sh->sg_tablesize) {
++              /* Reset this value */
++              dprintk((MYIOC_s_INFO_FMT
++                "Resetting sg_tablesize to %d from %d\n",
++                ioc->name, numSGE, sh->sg_tablesize));
++              sh->sg_tablesize = numSGE;
++      }
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+       /* Set the pci device pointer in Scsi_Host structure.
+@@ -1968,7 +890,7 @@ mptsas_probe(struct pci_dev *pdev, const
+        * (with size equal to req_depth*PtrSz!)
+        */
+       sz = ioc->req_depth * sizeof(void *);
+-      mem = kmalloc(sz, GFP_KERNEL);
++      mem = kmalloc(sz, GFP_ATOMIC);
+       if (mem == NULL) {
+               error = -ENOMEM;
+               goto out_mptsas_probe;
+@@ -1978,26 +900,25 @@ mptsas_probe(struct pci_dev *pdev, const
+       hd->ScsiLookup = (struct scsi_cmnd **) mem;
+       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+-          ioc->name, hd->ScsiLookup, sz));
++               ioc->name, hd->ScsiLookup, sz));
+-      for (ii=0; ii < ioc->NumberOfBuses; ii++) {
+-              /* Allocate memory for the device structures.
+-               * A non-Null pointer at an offset
+-               * indicates a device exists.
+-               */
+-              sz = ioc->DevicesPerBus * sizeof(void *);
+-              mem = kmalloc(sz, GFP_KERNEL);
+-              if (mem == NULL) {
+-                      error = -ENOMEM;
+-                      goto out_mptsas_probe;
+-              }
++      /* Allocate memory for the device structures.
++       * A non-Null pointer at an offset
++       * indicates a device exists.
++       * max_id = 1 + maximum id (hosts.h)
++       */
++      sz = sh->max_id * sizeof(void *);
++      mem = kmalloc(sz, GFP_ATOMIC);
++      if (mem == NULL) {
++              error = -ENOMEM;
++              goto out_mptsas_probe;
++      }
+-              memset(mem, 0, sz);
+-              ioc->Target_List[ii] = (struct _MPT_DEVICE *) mem;
++      memset(mem, 0, sz);
++      hd->Targets = (VirtDevice **) mem;
+-              dinitprintk((KERN_INFO " For Bus=%d, Target_List=%p sz=%d\n",
+-                  ii, mem, sz));
+-      }
++      dprintk((KERN_INFO
++        "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+       /* Clear the TM flags
+        */
+@@ -2013,18 +934,13 @@ mptsas_probe(struct pci_dev *pdev, const
+        */
+       hd->cmdPtr = NULL;
+-      /* Initialize this IOC's  timers
++      /* Initialize this SCSI Hosts' timers
+        * To use, set the timer expires field
+-       * and add_timer. Used for internally
+-         * generated commands.
++       * and add_timer
+        */
+-       init_timer(&hd->InternalCmdTimer);
+-       hd->InternalCmdTimer.data = (unsigned long) hd;
+-       hd->InternalCmdTimer.function = mptscsih_InternalCmdTimer_expired;
+-
+-       init_timer(&ioc->TMtimer);
+-       ioc->TMtimer.data = (unsigned long) ioc;
+-       ioc->TMtimer.function = mptscsih_TM_timeout;
++      init_timer(&hd->timer);
++      hd->timer.data = (unsigned long) hd;
++      hd->timer.function = mptscsih_timer_expired;
+       init_MUTEX(&ioc->hot_plug_semaphore);
+@@ -2038,50 +954,24 @@ mptsas_probe(struct pci_dev *pdev, const
+                   ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
+       }
+-      ddvprintk((MYIOC_s_INFO_FMT "mpt_pq_filter %x mpt_pq_filter %x\n",
+-          ioc->name, mpt_pq_filter, mpt_pq_filter));
++      ddvprintk((MYIOC_s_INFO_FMT
++              "mpt_pq_filter %x mpt_pq_filter %x\n",
++              ioc->name,
++              mpt_pq_filter,
++              mpt_pq_filter));
+       init_waitqueue_head(&hd->scandv_waitq);
+       hd->scandv_wait_done = 0;
+       hd->last_queue_full = 0;
+-        init_waitqueue_head(&hd->TM_waitq);
+-        hd->TM_wait_done = 0;
+-
+-      INIT_LIST_HEAD(&hd->target_reset_list);
+-
+-#if defined(CPQ_CIM)
+-      INIT_LIST_HEAD(&ioc->sas_device_info_list);
+-      init_MUTEX(&ioc->sas_device_info_mutex);
+-      port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+-      if (port_info && !mptsas_sas_io_unit_pg0(ioc, port_info))
+-              ioc->num_ports = port_info->num_phys;
+-      kfree(port_info);
+-#endif
+-
+       error = scsi_add_host (sh, &ioc->pcidev->dev);
+       if(error) {
+-              dprintk((KERN_ERR MYNAM "scsi_add_host failed\n"));
++              dprintk((KERN_ERR MYNAM
++                "scsi_add_host failed\n"));
+               goto out_mptsas_probe;
+       }
+       scsi_scan_host(sh);
+-
+-#if defined(CPQ_CIM)
+-      /*
+-       * Handling Inactive Volumes
+-       */
+-      if (!ioc->ir_firmware ||
+-          !ioc->raid_data.pIocPg2 ||
+-          !ioc->raid_data.pIocPg2->NumActiveVolumes)
+-      return 0;
+-
+-      for (ii = 0; ii < ioc->raid_data.pIocPg2->NumActiveVolumes; ii++)
+-              mptsas_add_device_component_ir(ioc,
+-                  ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeBus,
+-                  ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID);
+-#endif
+-
+       return 0;
+ out_mptsas_probe:
+@@ -2122,17 +1012,17 @@ mptsas_init(void)
+       show_mptmod_ver(my_NAME, my_VERSION);
+       mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
+-      mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
++      mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
+       mptsasInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
+       if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
+               devtprintk((KERN_INFO MYNAM
+-                  ": Registered for sas IOC event notifications\n"));
++                ": Registered for sas IOC event notifications\n"));
+       }
+-      if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) {
++      if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
+               dprintk((KERN_INFO MYNAM
+-                  ": Registered for IOC reset notifications\n"));
++                ": Registered for IOC reset notifications\n"));
+       }
+       return pci_register_driver(&mptsas_driver);
+@@ -2151,11 +1041,11 @@ mptsas_exit(void)
+       mpt_reset_deregister(mptsasDoneCtx);
+       dprintk((KERN_INFO MYNAM
+-          ": Deregistered for IOC reset notifications\n"));
++        ": Deregistered for IOC reset notifications\n"));
+       mpt_event_deregister(mptsasDoneCtx);
+       dprintk((KERN_INFO MYNAM
+-          ": Deregistered for IOC event notifications\n"));
++        ": Deregistered for IOC event notifications\n"));
+       mpt_deregister(mptsasInternalCtx);
+       mpt_deregister(mptsasTaskCtx);
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.h linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.h 2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.h        1970-01-01 01:00:00.000000000 +0100
+@@ -1,166 +0,0 @@
+-/*
+- *  linux/drivers/message/fusion/mptsas.h
+- *      High performance SCSI + LAN / Fibre Channel device drivers.
+- *      For use with PCI chip/adapter(s):
+- *          LSIFC9xx/LSI409xx Fibre Channel
+- *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+- *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
+- *
+- */
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*
+-    This program is free software; you can redistribute it and/or modify
+-    it under the terms of the GNU General Public License as published by
+-    the Free Software Foundation; version 2 of the License.
+-
+-    This program is distributed in the hope that it will be useful,
+-    but WITHOUT ANY WARRANTY; without even the implied warranty of
+-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-    GNU General Public License for more details.
+-
+-    NO WARRANTY
+-    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+-    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+-    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+-    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+-    solely responsible for determining the appropriateness of using and
+-    distributing the Program and assumes all risks associated with its
+-    exercise of rights under this Agreement, including but not limited to
+-    the risks and costs of program errors, damage to or loss of data,
+-    programs or equipment, and unavailability or interruption of operations.
+-
+-    DISCLAIMER OF LIABILITY
+-    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+-    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+-    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+-    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+-    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+-    USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+-    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+-
+-    You should have received a copy of the GNU General Public License
+-    along with this program; if not, write to the Free Software
+-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-*/
+-
+-#ifndef MPTSAS_H_INCLUDED
+-#define MPTSAS_H_INCLUDED
+-/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-
+-struct mptscsih_target_reset {
+-      struct list_head        list;
+-      EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
+-      u8      target_reset_issued;
+-};
+-
+-enum mptsas_hotplug_action {
+-      MPTSAS_ADD_DEVICE,
+-      MPTSAS_DEL_DEVICE,
+-      MPTSAS_ADD_INACTIVE_VOLUME,
+-      MPTSAS_PHYSDISK_ADD,
+-};
+-
+-struct mptsas_hotplug_event {
+-      struct work_struct      work;
+-      MPT_ADAPTER             *ioc;
+-      enum mptsas_hotplug_action event_type;
+-      u64                     sas_address;
+-      u32                     channel;
+-      u32                     id;
+-      u32                     device_info;
+-      u16                     handle;
+-      u16                     parent_handle;
+-      u8                      phy_id;
+-      u8                      refresh_raid_config_pages;
+-};
+-
+-/*
+- * SAS topology structures
+- *
+- * The MPT Fusion firmware interface spreads information about the
+- * SAS topology over many manufacture pages, thus we need some data
+- * structure to collect it and process it for the SAS transport class.
+- */
+-
+-struct mptsas_devinfo {
+-      u16     handle;         /* unique id to address this device */
+-      u16     handle_parent;  /* unique id to address parent device */
+-      u16     handle_enclosure; /* enclosure identifier of the enclosure */
+-      u16     slot;           /* physical slot in enclosure */
+-      u8      phy_id;         /* phy number of parent device */
+-      u8      port_id;        /* sas physical port this device
+-                                 is assoc'd with */
+-      u8      id;             /* logical target id of this device */
+-      u32     phys_disk_num;  /* phys disk id, for csmi-ioctls */
+-      u8      channel;        /* logical bus number of this device */
+-      u64     sas_address;    /* WWN of this device,
+-                                 SATA is assigned by HBA,expander */
+-      u32     device_info;    /* bitfield detailed info about this device */
+-#if !defined(MPT_WIDE_PORT_API)
+-      u8      wide_port_enable;       /* when set, this is part of wide port*/
+-#endif
+-};
+-
+-/*
+- * Specific details on ports, wide/narrow
+- */
+-struct mptsas_portinfo_details{
+-#if !defined(MPT_WIDE_PORT_API)
+-      u8      port_id;        /* port number provided to transport */
+-      u8      rphy_id;        /* phy index used for reporting end device*/
+-      u32     device_info;    /* bitfield detailed info about this device */
+-#endif
+-      u16     num_phys;       /* number of phys beloing to this port */
+-      u64     phy_bitmask;    /* this needs extending to support 128 phys */
+-      struct sas_rphy *rphy; /* rphy for end devices */
+-#if defined(MPT_WIDE_PORT_API)
+-      struct sas_port *port;  /* transport layer port object */
+-#endif
+-      struct scsi_target *starget;
+-      struct mptsas_portinfo *port_info;
+-};
+-
+-struct mptsas_phyinfo {
+-      u8      phy_id;                 /* phy index */
+-      u8      port_id;                /* port number this phy is part of */
+-      u8      negotiated_link_rate;   /* nego'd link rate for this phy */
+-      u8      hw_link_rate;           /* hardware max/min phys link rate */
+-      u8      programmed_link_rate;   /* programmed max/min phy link rate */
+-#if defined(MPT_WIDE_PORT_API)
+-      u8      sas_port_add_phy;       /* flag to request sas_port_add_phy*/
+-#endif
+-#if defined(CPQ_CIM)
+-      u8      change_count;           /* change count of the phy */
+-      u8      port_flags;             /* info wrt host sas ports */
+-#endif
+-      u32     phy_info;               /* various info wrt the phy */
+-      struct mptsas_devinfo identify; /* point to phy device info */
+-      struct mptsas_devinfo attached; /* point to attached device info */
+-      struct sas_phy *phy;
+-      struct mptsas_portinfo *portinfo;
+-      struct mptsas_portinfo_details * port_details;
+-};
+-
+-struct mptsas_portinfo {
+-      struct list_head list;
+-      u16             handle;         /* unique id to address this */
+-      u16             num_phys;       /* number of phys */
+-      struct mptsas_phyinfo *phy_info;
+-};
+-
+-struct mptsas_enclosure {
+-      u64     enclosure_logical_id;   /* The WWN for the enclosure */
+-      u16     enclosure_handle;       /* unique id to address this */
+-      u16     flags;                  /* details enclosure management */
+-      u16     num_slot;               /* num slots */
+-      u16     start_slot;             /* first slot */
+-      u8      start_id;               /* starting logical target id */
+-      u8      start_channel;          /* starting logical channel id */
+-      u8      sep_id;                 /* SEP device logical target id */
+-      u8      sep_channel;            /* SEP channel logical channel id */
+-};
+-
+-/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-#endif
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptscsi.c linux-2.6.9-55.0.12/drivers/message/fusion/mptscsi.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptscsi.c        2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptscsi.c       2007-11-02 09:10:23.000000000 +0100
+@@ -3,8 +3,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptscsih.c,v 1.1.2.4 2003/05/07 14:08:34 Exp $
+  */
+@@ -74,7 +74,6 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -83,6 +82,13 @@ typedef struct _BIG_SENSE_BUF {
+ } BIG_SENSE_BUF;
+ #define OEM_TLR_COMMAND                       0xC2
++#define MPT_SCANDV_GOOD                       (0x00000000) /* must be 0 */
++#define MPT_SCANDV_DID_RESET          (0x00000001)
++#define MPT_SCANDV_SENSE              (0x00000002)
++#define MPT_SCANDV_SOME_ERROR         (0x00000004)
++#define MPT_SCANDV_SELECTION_TIMEOUT  (0x00000008)
++#define MPT_SCANDV_ISSUE_SENSE                (0x00000010)
++#define MPT_SCANDV_FALLBACK           (0x00000020)
+ #define MPT_SCANDV_MAX_RETRIES                (10)
+@@ -116,37 +122,44 @@ typedef struct _dv_parameters {
+ int           mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+ static void   mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
+ int           mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
++
+ static int    mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
+                                SCSIIORequest_t *pReq, int req_idx);
+ static void   mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
+ static void   mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
+ static int    mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
+-static int    SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
+-int           mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u8 lun, int ctx2abort, ulong timeout);
+-static int    mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u8 lun, int ctx2abort, ulong timeout);
++static int    mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
++static u32    SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
++
++int           mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
++static int    mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+ int           mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+ int           mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+-static void   mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus, int id, u8 lun, char *data, int dlen);
+-static void   mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *pTarget, char byte56);
+-static void   mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int id);
+-static int    mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int id, int bus);
++
++static void   mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
++static void   mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
++static void   mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
++static void   mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
++static void   mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
++static int    mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
++static int    mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
+ int           mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+-void           mptscsih_InternalCmdTimer_expired(unsigned long data);
++void          mptscsih_timer_expired(unsigned long data);
+ static int    mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+ static int    mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
+ static void   mptscsih_domainValidation(void *hd);
+-static int    mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id);
++static int    mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
+ static void   mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
+-static int    mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int id);
+-static void    mptscsih_post_PendingMF_command(MPT_ADAPTER *ioc);
++static int    mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
+ static void   mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
+-static MPT_FRAME_HDR * mptscsih_search_PendingMF(MPT_ADAPTER *ioc, struct scsi_cmnd * sc);
+ static void   mptscsih_fillbuf(char *buffer, int size, int index, int width);
++static void   mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
+ #endif
+-static void   mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevice *pTarget);
++static void
++mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevice *pTarget);
+ void          mptscsih_remove(struct pci_dev *);
+ // This was changed in the 2.6.13 kernel
+@@ -169,6 +182,8 @@ int mptscsih_resume(struct pci_dev *pdev
+  */
+ static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
+ static int dvtaskQ_active = 0;
++static int dvtaskQ_release = 0;
++static struct work_struct     dvTaskQ_task;
+ #endif
+@@ -560,7 +575,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+       }
+       sc = hd->ScsiLookup[req_idx];
+-      hd->ScsiLookup[req_idx] = NULL;
+       if (sc == NULL) {
+               MPIHeader_t *hdr = (MPIHeader_t *)mf;
+@@ -575,10 +589,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+               mptscsih_freeChainBuffers(ioc, req_idx);
+               return 1;
+       }
+-      if ((unsigned char *)mf != sc->host_scribble) {
+-              mptscsih_freeChainBuffers(ioc, req_idx);
+-              return 1;
+-      }
+       sc->result = DID_OK << 16;              /* Set default reply as OK */
+       pScsiReq = (SCSIIORequest_t *) mf;
+@@ -601,12 +611,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+               u32      xfer_cnt;
+               u16      ioc_status;
+               u8       scsi_state, scsi_status;
+-#ifdef MPT_DEBUG_ERROR
+-               u8       ii, skey, asc, ascq;
+-#endif
+-              struct _MPT_DEVICE      *pMptTarget;
+-              VirtDevice      *pTarget;
+-              int      bus, id;
++              VirtDevice              *pTarget;
++              int      target;
+               ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+               scsi_state = pScsiReply->SCSIState;
+@@ -627,35 +633,18 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                       ioc_status = MPI_IOCSTATUS_SUCCESS;
+               }
+-#ifdef MPT_DEBUG_ERR
+-              if (ioc_status != MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE) {        /* 0x0043 */
+-                      derrprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
+-                              "IOCStatus=%04x SCSIState=%02x SCSIStatus=%02x\n"
+-                              "resid=%d bufflen=%d xfer_cnt=%d\n",
+-                              ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+-                              ioc_status, scsi_state, scsi_status, sc->resid,
+-                              sc->request_bufflen, xfer_cnt));
+-              }
+-#endif
++              dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
++                      "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
++                      "resid=%d bufflen=%d xfer_cnt=%d\n",
++                      ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
++                      ioc_status, scsi_state, scsi_status, sc->resid,
++                      sc->request_bufflen, xfer_cnt));
+-              if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID){
++              if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
+                       mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
+-#ifdef MPT_DEBUG_ERROR
+-                       skey = sc->sense_buffer[2];
+-                       asc  = sc->sense_buffer[12];
+-                       ascq = sc->sense_buffer[13];
+-                       derrprintk((MYIOC_s_WARN_FMT
+-                               "id=%d SenseKey:ASC:ASCQ = (%x:%02x:%02x) CDB:\n",
+-                               ioc->name, pScsiReq->TargetID,
+-                               skey, asc, ascq));
+-
+-                       for (ii=0; ii<pScsiReq->CDBLength; ii++) {
+-                               printk("%02x ", pScsiReq->CDB[ii]);
+-                       }
+-                       printk("\n");
+-#endif
+-  } else if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && pScsiReply->ResponseInfo) {
++              if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
++                  pScsiReply->ResponseInfo) {
+                       printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
+                       "FCP_ResponseInfo=%08xh\n",
+                       ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+@@ -670,13 +659,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                        * killing interrupt handler:-(
+                        */
+                       sc->result = SAM_STAT_BUSY;
+-#ifdef MPT_DEBUG_FAIL
+-                       derrprintk((MYIOC_s_ERR_FMT
+-                               "id=%d MPI_IOCSTATUS_BUSY\n",
+-                               ioc->name, pScsiReq->TargetID));
+-//                     panic ("IOCSTATUS_BUSY!!!!!\n");
+-#endif
+-
+                       break;
+               case MPI_IOCSTATUS_SCSI_INVALID_BUS:            /* 0x0041 */
+@@ -688,15 +670,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                       /* Spoof to SCSI Selection Timeout! */
+                       sc->result = DID_NO_CONNECT << 16;
+-                      bus = pScsiReq->Bus;
+-                      id = pScsiReq->TargetID;
+-                      if ( ioc->bus_type == SPI ) {
+-                              if (hd->sel_timeout[id] < 0xFFFF)
+-                                      hd->sel_timeout[pScsiReq->TargetID]++;
+-                      }
++                      target = pScsiReq->TargetID;
++                      if (hd->sel_timeout[target] < 0xFFFF)
++                              hd->sel_timeout[pScsiReq->TargetID]++;
+-                      pMptTarget = ioc->Target_List[bus];
+-                      pTarget = (VirtDevice *)pMptTarget->Target[id];
++                      pTarget = hd->Targets[target];
+                       if ( pTarget ) {
+                               if (pTarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
+@@ -710,8 +688,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                                       } else {
+                                               SEPMsg = (SEPRequest_t *)mf;
+                                               SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
+-                                              SEPMsg->Bus = pTarget->bus;
+-                                              SEPMsg->TargetID = pTarget->id;
++                                              SEPMsg->Bus = pTarget->bus_id;
++                                              SEPMsg->TargetID = pTarget->target_id;
+                                               SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
+                                               SEPMsg->SlotStatus = MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED;
+                                               pTarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
+@@ -726,24 +704,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+               case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
+                       if ( ioc->bus_type == SAS ) {
+                               u16      status = le16_to_cpu(pScsiReply->IOCStatus);
+-                              u32      log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+-//                            sc->result = DID_RESET << 16;
+-                              sc->result = DID_SOFT_ERROR << 16;
+                               if (status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+-                                      if ((log_info & 0xFFFF0000) ==
+-                                              SAS_LOGINFO_NEXUS_LOSS) {
++                                      u32      log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
++                                      log_info &= 0xFFFF0000;  /* mask subcodes */
++                                      dreplyprintk((KERN_NOTICE "IOC_TERMINATED: ha=%d id=%d lun=%d:\n"
++                      "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh "
++                      "loginfo=%08x\n"
++                      ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
++                      status, scsi_state, scsi_status, log_info));
++                                      if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
+                                               sc->result = (DID_BUS_BUSY << 16);
++                                              break;
+                                       }
++                              } else {
++                                      dreplyprintk((KERN_NOTICE "IOC_TERMINATED: ha=%d id=%d lun=%d:\n"
++                      "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n",
++                      ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
++                      status, scsi_state, scsi_status));
+                               }
+-                              derrprintk((KERN_NOTICE "IOC_TERMINATED: "
+-                                      "ha=%d id=%d lun=%d "
+-                                      "IOCStatus=%04x SCSIState=%02x\n"
+-                                      "SCSIStatus=%02x LogInfo=%08x "
+-                                      "sc->result=%08x sc=%p\n",
+-                                      ioc->id, pScsiReq->TargetID,
+-                                      pScsiReq->LUN[1], status, scsi_state,
+-                                      scsi_status, log_info, sc->result, sc));
+-                              break;
+                       }  /* allow non-SAS & non-NEXUS_LOSS to drop into below code */
+               case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
+@@ -775,7 +753,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                       } else {
+                               sc->result = DID_SOFT_ERROR << 16;
+                       }
+-//                    derrprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
++//                    dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
+                       printk("RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id);
+                       break;
+ #else
+@@ -784,7 +762,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                               sc->result=DID_SOFT_ERROR << 16;
+                       else /* Sufficient data transfer occurred */
+                               sc->result = (DID_OK << 16) | scsi_status;
+-                      derrprintk((KERN_NOTICE
++                      dreplyprintk((KERN_NOTICE 
+                           "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
+                       break;
+ #endif
+@@ -804,9 +782,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                                               sc->result = SAM_STAT_BUSY;
+                                       else
+                                               sc->result = DID_SOFT_ERROR << 16;
+- derrprintk((KERN_NOTICE " xfer_cnt=%d < sc->underflow=%d result=%08x\n",xfer_cnt, sc->underflow, sc->result));
+-
+-                                 }
++                              }
+                               if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
+                                       /* What to do?
+                                       */
+@@ -818,6 +794,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                               }
+                       }
++                      dreplyprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
++                                      sc->underflow));
++                      dreplyprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
+                       /* Report Queue Full
+                        */
+                       if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
+@@ -896,18 +875,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                       break;
+               }       /* switch(ioc_status) */
+-               if (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) {
+-                       derrprintk((KERN_NOTICE "ha=%d id=%d lun=%d "
+-                               "IOCStatus=%04x SCSIState=%02x\n"
+-                               "SCSIStatus=%02x "
+-                               "sc->result=%08x sc=%p\n",
+-                               ioc->id, pScsiReq->TargetID,
+-                               pScsiReq->LUN[1], ioc_status,
+-                               scsi_state, scsi_status, sc->result,
+-                               sc));
+-               }
+-              } /* end of address reply case */
++              dreplyprintk((KERN_NOTICE "  sc->result is %08xh\n", sc->result));
++      } /* end of address reply case */
+       /* Unmap the DMA buffers, if any. */
+       if (sc->use_sg) {
+@@ -918,7 +888,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
+                               sc->request_bufflen, sc->sc_data_direction);
+       }
+-      sc->host_scribble = NULL;
++      hd->ScsiLookup[req_idx] = NULL;
++
+       sc->scsi_done(sc);              /* Issue the command callback */
+       /* Free Chain buffers */
+@@ -945,9 +916,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOS
+       int              ii;
+       int              max = ioc->req_depth;
+-
+-drsprintk((MYIOC_s_WARN_FMT ": %s entered\n",ioc->name, __FUNCTION__));
+-
++      dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
+       for (ii= 0; ii < max; ii++) {
+               if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
+@@ -959,24 +928,8 @@ drsprintk((MYIOC_s_WARN_FMT ": %s entere
+                       hd->ScsiLookup[ii] = NULL;
+                       mf = MPT_INDEX_2_MFPTR(ioc, ii);
+-
+-/*                     drsprintk((MYIOC_s_WARN_FMT "flush mf=%p sc=%p\n",
+-                               ioc->name, mf, SCpnt));
+-                       DBG_DUMP_RESET_REQUEST_FRAME(ioc, mf) */
+-
+-
+-                      /* Free Chain buffers */
+-                      mptscsih_freeChainBuffers(ioc, ii);
+-
+-                      /* Free Message frames */
+-                      mpt_free_msg_frame(ioc, mf);
+-
+-                      if ((unsigned char *)mf != SCpnt->host_scribble) {
+-                     drsprintk(( "%s Skipping scsi_done mf=%p host_scribble=%p\n",
+-                         __FUNCTION__, mf, SCpnt->host_scribble));
+-
+-                              continue;
+-                      }
++                      dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
++                                      mf, SCpnt));
+                       /* Set status, free OS resources (SG DMA buffers)
+                        * Do OS callback
+@@ -993,14 +946,20 @@ drsprintk((MYIOC_s_WARN_FMT ": %s entere
+                                       SCpnt->request_bufflen,
+                                       SCpnt->sc_data_direction);
+                       }
+-                        SCpnt->result = (DID_BUS_BUSY << 16);
++                      SCpnt->result = DID_RESET << 16;
+                       SCpnt->host_scribble = NULL;
++
++                      /* Free Chain buffers */
++                      mptscsih_freeChainBuffers(ioc, ii);
++
++                      /* Free Message frames */
++                      mpt_free_msg_frame(ioc, mf);
++
+                       SCpnt->scsi_done(SCpnt);        /* Issue the command callback */
+               }
+       }
+-drsprintk((MYIOC_s_WARN_FMT ": %s exiting\n", ioc->name, __FUNCTION__));
+-
++      return;
+ }
+ /*
+@@ -1010,7 +969,7 @@ drsprintk((MYIOC_s_WARN_FMT ": %s exitin
+  *            Do NOT access the referenced scsi_cmnd structure or
+  *            members. Will cause either a paging or NULL ptr error.
+  *    @hd: Pointer to a SCSI HOST structure
+- *    @id: target id
++ *    @target: target id
+  *    @lun: lun
+  *
+  *    Returns: None.
+@@ -1018,47 +977,43 @@ drsprintk((MYIOC_s_WARN_FMT ": %s exitin
+  *    Called from slave_destroy.
+  */
+ static void
+-mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint id, uint lun)
++mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
+ {
+-      MPT_ADAPTER             *ioc = hd->ioc;
+       SCSIIORequest_t *mf = NULL;
+       int              ii;
+-      int              max = ioc->req_depth;
++      int              max = hd->ioc->req_depth;
+       struct scsi_cmnd *sc;
+-      dsprintk((KERN_INFO MYNAM ": search_running id %d lun %d max %d\n",
+-                      id, lun, max));
++      dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
++                      target, lun, max));
+       for (ii=0; ii < max; ii++) {
+               if ((sc = hd->ScsiLookup[ii]) != NULL) {
+-                      mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
++                      mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
+                       dsprintk(( "search_running: found (sc=%p, mf = %p)\n",
+                                       hd->ScsiLookup[ii], mf));
+                       if (mf == NULL)
+                               continue;
+-                      dsprintk(( "search_running: found (sc=%p, mf = %p) id %d, lun %d \n",
++                      dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
+                                       hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
+-                      if ((mf->TargetID != ((u8)id)) || (mf->LUN[1] != ((u8) lun)))
++                      if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
+                               continue;
+                       /* Cleanup
+                        */
+                       hd->ScsiLookup[ii] = NULL;
+-                      mptscsih_freeChainBuffers(ioc, ii);
+-                      mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
+-                      if ((unsigned char *)mf != sc->host_scribble) {
+-                              continue;
+-                      }
++                      mptscsih_freeChainBuffers(hd->ioc, ii);
++                      mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
+                       if (sc->use_sg) {
+-                              pci_unmap_sg(ioc->pcidev,
++                              pci_unmap_sg(hd->ioc->pcidev,
+                               (struct scatterlist *) sc->request_buffer,
+                                       sc->use_sg,
+                                       sc->sc_data_direction);
+                       } else if (sc->request_bufflen) {
+-                              pci_unmap_single(ioc->pcidev,
++                              pci_unmap_single(hd->ioc->pcidev,
+                                       sc->SCp.dma_handle,
+                                       sc->request_bufflen,
+                                       sc->sc_data_direction);
+@@ -1068,8 +1023,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HO
+                       sc->scsi_done(sc);
+               }
+       }
+-      dsprintk((KERN_INFO MYNAM ": search_running id %d lun %d completed\n",
+-                      id, lun));
++      dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d completed\n",
++                      target, lun));
+       return;
+ }
+@@ -1169,66 +1124,9 @@ mptscsih_sendIOCInit(MPT_SCSI_HOST *hd)
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*    mptscsih_TM_timeout - Call back for timeout on a
+- *    task management request.
+- *    @data: Pointer to MPT_ADAPTER recast as an unsigned long
+- *
+- */
+-void mptscsih_TM_timeout(unsigned long data)
+-{
+-      MPT_ADAPTER     *ioc=(MPT_ADAPTER *)data;
+-      MPT_SCSI_HOST   *hd =(MPT_SCSI_HOST *)ioc->sh->hostdata;
+-      int              retval;
+-      u32              ioc_state;
+-
+-      dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_TM_timeout: "
+-                 "TM request timed out!\n", ioc->name));
+-
+-      /* Delete the timer that triggered this callback.
+-       * Remark: DEL_TIMER checks to make sure timer is active
+-       * before deleting.
+-       */
+-      del_timer(&ioc->TMtimer);
+-
+-      mpt_free_msg_frame(ioc, ioc->tmPtr);
+-
+-      ioc->tmPtr = NULL;
+-
+-      dtmprintk((MYIOC_s_WARN_FMT "%s: Calling mpt_SendIocReset MUR!\n",
+-              ioc->name, __FUNCTION__));
+-      if ((retval = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP)) != 0) {
+-              ioc_state = mpt_GetIocState(ioc, 0);
+-              dfailprintk((MYIOC_s_WARN_FMT "%s: IOC MUR failed! ioc_state=%08x\n",
+-                      ioc->name, __FUNCTION__, ioc_state));
+-//            panic ("IOC MUR Failed");
+-              ioc->IOCResetInProgress = 0;
+-
+-              if ((retval = mpt_HardResetHandler(ioc, NO_SLEEP)) < 0){
+-                      printk(KERN_WARNING "%s: %s: HardResetHandler FAILED!!\n",
+-                              ioc->name, __FUNCTION__);
+-              } else {
+-                      dtmprintk((MYIOC_s_WARN_FMT "%s: HardResetHandler succeeded!!\n",
+-                              ioc->name, __FUNCTION__));
+-              }
+-      } else {
+-              dtmprintk((MYIOC_s_WARN_FMT "IOC MUR succeeded\n", ioc->name));
+-              mptscsih_flush_running_cmds(hd);
+-              dtmprintk((MYIOC_s_WARN_FMT "Calling do_ioc_recovery! \n", ioc->name));
+-              if ((retval = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, NO_SLEEP)) != 0) {
+-                      dfailprintk((MYIOC_s_ERR_FMT "%s: (%d) ioc_recovery failed\n", ioc->name, __FUNCTION__, retval));
+-              } else {
+-                      dtmprintk((MYIOC_s_WARN_FMT "%s:Successful do_ioc_recovery! \n", ioc->name, __FUNCTION__));
+-              }
+-      }
+-      hd->TM_wait_done = 1;
+-      wake_up(&hd->TM_waitq);
+-}
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*    mptscsih_writeFCPortPage3  - write FC Port Page 3
+  *    @hd: Pointer to a SCSI Host Structure
+- *    @bus: write FC Port Page 3 for this bus
+- *    @id: write FC Port Page 3 for this target ID
++ *    @target_id: write FC Port Page 3 for this target ID
+  *
+  *    Return: -EAGAIN if unable to obtain a Message Frame
+  *            or 0 if success.
+@@ -1236,7 +1134,7 @@ void mptscsih_TM_timeout(unsigned long d
+  *    Remark: We do not wait for a return, write pages sequentially.
+  */
+ static int
+-mptscsih_writeFCPortPage3(MPT_SCSI_HOST *hd, int bus, int id)
++mptscsih_writeFCPortPage3(MPT_SCSI_HOST *hd, int target_id)
+ {
+       MPT_ADAPTER             *ioc = hd->ioc;
+       Config_t                *pReq;
+@@ -1247,7 +1145,6 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+       u32                      frameOffset;
+       u32                      flagsLength;
+       int                      ii;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice              *pTarget;
+       /* Get a MF for this command.
+@@ -1287,10 +1184,9 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+               pReq->Header.PageType = MPI_CONFIG_PAGETYPE_FC_PORT |
+                               MPI_CONFIG_PAGEATTR_PERSISTENT;
+       pReq->PageAddress = cpu_to_le32(MPI_FC_PORT_PGAD_FORM_INDEX |
+-                                      id);
++                                      target_id);
+-      pMptTarget = ioc->Target_List[bus];
+-      pTarget = pMptTarget->Target[id];
++      pTarget = hd->Targets[target_id];
+       FCPort3->Header.PageVersion = MPI_FCPORTPAGE3_PAGEVERSION;
+       FCPort3->Header.PageLength = sizeof(FCPortPage3_t) / 4;
+@@ -1299,8 +1195,8 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+                                  MPI_CONFIG_PAGEATTR_PERSISTENT;
+               FCPort3->Entry[0].PhysicalIdentifier.WWN.WWPN = pTarget->WWPN;
+               FCPort3->Entry[0].PhysicalIdentifier.WWN.WWNN = pTarget->WWNN;
+-      FCPort3->Entry[0].TargetID = id;
+-      FCPort3->Entry[0].Bus = bus;
++              FCPort3->Entry[0].TargetID = pTarget->target_id;
++              FCPort3->Entry[0].Bus = pTarget->bus_id;
+       FCPort3->Entry[0].Flags = cpu_to_le16(MPI_PERSISTENT_FLAGS_ENTRY_VALID);
+       /* Add a SGE to the config request.
+@@ -1308,7 +1204,7 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+       flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sizeof(FCPortPage3_t);
+       mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
+-      drsprintk((MYIOC_s_INFO_FMT "writeFCPortPage3: bus=%d id=%d\n", ioc->name, , bus, id));
++      drsprintk((MYIOC_s_INFO_FMT "writeFCPortPage3: target=%d\n", ioc->name, target_id));
+       mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+@@ -1320,7 +1216,7 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+  *    mptscsih_readFCDevicePage0 - returns FC Device Page 0 data
+  *    @ioc: Pointer to MPT_ADAPTER structure
+  *    @bus: bus id
+- *    @id: target id
++ *    @targetId: target id
+  *    @fcDevicePage: FC Device Page 0 data
+  *
+  *    Returns count of number bytes copied into @fcDevicePage
+@@ -1328,7 +1224,7 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST 
+  */
+ int
+-mptscsih_readFCDevicePage0(MPT_ADAPTER *ioc, u8 bus, u8 id, pFCDevicePage0_t fcDevicePage)
++mptscsih_readFCDevicePage0(MPT_ADAPTER *ioc, u8 bus, u8 targetId, pFCDevicePage0_t fcDevicePage)
+ {
+       ConfigPageHeader_t       hdr;
+       CONFIGPARMS              cfg;
+@@ -1348,7 +1244,7 @@ mptscsih_readFCDevicePage0(MPT_ADAPTER *
+       cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+       cfg.dir = 0;
+-      cfg.pageAddr = (bus << 8) + id + MPI_FC_DEVICE_PGAD_FORM_BUS_TID;
++      cfg.pageAddr = (bus << 8) + targetId + MPI_FC_DEVICE_PGAD_FORM_BUS_TID;
+       cfg.timeout = 0;
+       if ((rc = mpt_config(ioc, &cfg)) != 0)
+@@ -1436,16 +1332,15 @@ mptscsih_remove(struct pci_dev *pdev)
+               spin_unlock_irqrestore(&dvtaskQ_lock, flags);
+       }
+       if (!count)
+-   printk(KERN_ERR MYNAM ": %s: ERROR - DV thread still active!\n",
+-            ioc->name);
+-#ifdef MPT_DEBUG_DV
++              printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
++#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
+       else
+-              printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", ioc->name,10 * HZ, count);
++              printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
+ #endif
+ #endif
+-      dexitprintk((KERN_INFO MYNAM ": %s ioc=%p hd=%p MaxDevices=%d\n",
+-              ioc->name, ioc, hd, ioc->facts.MaxDevices));
++      dexitprintk((KERN_INFO MYNAM ": %s ioc=%p hd=%p Targets=%p MaxDevices=%d\n", 
++              ioc->name, ioc, hd, hd->Targets, ioc->facts.MaxDevices));
+ // This was changed in the 2.6.13 kernel
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+       mptscsih_shutdown(&pdev->dev);
+@@ -1453,19 +1348,19 @@ mptscsih_remove(struct pci_dev *pdev)
+       mptscsih_shutdown(pdev);
+ #endif
+-      dexitprintk((KERN_INFO MYNAM ": %s: calling scsi_remove_host ioc=%p host=%p\n",
++      dexitprintk((KERN_INFO MYNAM ": %s: calling scsi_remove_host ioc=%p host=%p\n", 
+               ioc->name, ioc, host));
+       scsi_remove_host(host);
+       dexitprintk((KERN_INFO MYNAM ": %s: scsi_remove_host completed\n", ioc->name));
+       if (hd->ScsiLookup != NULL) {
+-              sz1 = ioc->req_depth * sizeof(void *);
++              sz1 = hd->ioc->req_depth * sizeof(void *);
+               kfree(hd->ScsiLookup);
+               hd->ScsiLookup = NULL;
+               dprintk((MYIOC_s_INFO_FMT
+                       "Free'd ScsiLookup (%d) memory\n",
+-                      ioc->name, sz1));
++                      hd->ioc->name, sz1));
+       }
+       if (hd->info_kbuf != NULL)
+@@ -1473,7 +1368,7 @@ mptscsih_remove(struct pci_dev *pdev)
+       /* NULL the Scsi_Host pointer
+        */
+-      ioc->sh = NULL;
++      hd->ioc->sh = NULL;
+       scsi_host_put(host);
+@@ -1498,36 +1393,25 @@ mptscsih_shutdown(struct pci_dev *pdev)
+ {
+        MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
+ #endif
+-      struct Scsi_Host        *host;
++      struct Scsi_Host        *host = ioc->sh;
+       MPT_SCSI_HOST           *hd;
+-      host = ioc->sh;
+-
+       if(!host)
+               return;
+       hd = (MPT_SCSI_HOST *)host->hostdata;
+-      dexitprintk((KERN_INFO MYNAM ": %s: ioc=%p hd=%p\n",
+-              __FUNCTION__, ioc, hd));
+-
+       /* Flush the cache of this adapter
+        */
+-      if(hd != NULL) {
+-              dexitprintk((KERN_INFO MYNAM ": Calling mptscsih_synchronize_cache for %s\n",
+-                      ioc->name));
++      if(hd != NULL)
+               mptscsih_synchronize_cache(hd, 0);
+-              dexitprintk((KERN_INFO MYNAM ": mptscsih_synchronize_cache for %s completed\n",
+-                      ioc->name));
+-      }
+-      dexitprintk((KERN_INFO MYNAM ": %s done: ioc=%p hd=%p\n",
+-              __FUNCTION__, ioc, hd));
++
+ }
+ #ifdef CONFIG_PM
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+- *    mptscsih_suspend - Fusion MPT scsi driver suspend routine.
++ *    mptscsih_suspend - Fusion MPT scsie driver suspend routine.
+  *
+  *
+  */
+@@ -1566,7 +1450,7 @@ mptscsih_resume(struct pci_dev *pdev)
+               return 0;
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+-/*    {
++      {
+       unsigned long lflags;
+       spin_lock_irqsave(&dvtaskQ_lock, lflags);
+       if (!dvtaskQ_active) {
+@@ -1578,7 +1462,7 @@ mptscsih_resume(struct pci_dev *pdev)
+       } else {
+               spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
+       }
+-      } */
++      }
+ #endif
+       return 0;
+ }
+@@ -1732,13 +1616,10 @@ int
+ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+ {
+       MPT_SCSI_HOST           *hd;
+-      MPT_ADAPTER             *ioc;
+       MPT_FRAME_HDR           *mf;
+       SCSIIORequest_t         *pScsiReq;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice              *pTarget;
+-        unsigned long                  flags;
+-        int    bus, id;
++      int      target;
+       int      lun;
+       u32      datalen;
+       u32      scsictl;
+@@ -1746,34 +1627,18 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
+       int      my_idx;
+       int      ii;
+-      /* EDM Debug */
+-//    mptscsih_scsi_print_command(SCpnt);
+-
+       hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+-      ioc = hd->ioc;
+-      bus = SCpnt->device->channel;
+-      id = SCpnt->device->id;
++      target = SCpnt->device->id;
+       lun = SCpnt->device->lun;
+       SCpnt->scsi_done = done;
+-       spin_lock_irqsave(&ioc->diagLock, flags);
+-       if (ioc->IOCResetInProgress) {
+-               dfailprintk((MYIOC_s_WARN_FMT "qcmd, SCpnt=%p IOCResetInProgress!!\n",
+-                            ioc->name, SCpnt));
+-               spin_unlock_irqrestore(&ioc->diagLock, flags);
+-               goto fail;
+-       }
+-       spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+-
+-      pMptTarget = ioc->Target_List[bus];
+-      pTarget = pMptTarget->Target[id];
++      pTarget = hd->Targets[target];
+       if ( pTarget ) {
+               if ( lun > pTarget->last_lun ) {
+                       dsprintk((MYIOC_s_INFO_FMT
+                               "qcmd: lun=%d > last_lun=%d on id=%d\n",
+-                              ioc->name, lun, pTarget->last_lun, id));
++                              hd->ioc->name, lun, pTarget->last_lun, target));
+                       SCpnt->result = DID_BAD_TARGET << 16;
+                       SCpnt->scsi_done(SCpnt);
+                       return 0;
+@@ -1782,31 +1647,32 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
+                * allocated, use the Inquiry data to determine if device 
+                * supports tagged.
+               */
+-              if ( pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
++              if ( (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
++                  && (SCpnt->device->tagged_supported)) {
+                       scsictl = MPI_SCSIIO_CONTROL_SIMPLEQ;
+-               else
++              } else {
+                       scsictl = MPI_SCSIIO_CONTROL_UNTAGGED;
++              }
+-      } else {
++      } else
+               scsictl = MPI_SCSIIO_CONTROL_UNTAGGED;
+-dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=%02x id=%d lun=%d Null pTarget, sending Untagged\n",
+-                       ioc->name, SCpnt->cmnd[0], id, lun));
+-               if (ioc->bus_type == SPI) {
+-                       dnegoprintk(("writeSDP1: id=%d Async/Narrow\n",
+-                               id));
+-                       mpt_writeSDP1(ioc, 0, id, 0);
+-               }
++      dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
++                      (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
+- }
++      if (hd->resetPending) {
++              dfailprintk((MYIOC_s_INFO_FMT "QueueCmd, SCpnt=%p resetPending!!\n",
++                              hd->ioc->name, SCpnt));
++              return SCSI_MLQUEUE_HOST_BUSY;
++      }
+       /*
+        *  Put together a MPT SCSI request...
+        */
+-      if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
++      if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
+               dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-                  ioc->name,__FUNCTION__));
+-                  goto fail;
+-               }
++                  hd->ioc->name,__FUNCTION__));
++              return SCSI_MLQUEUE_HOST_BUSY;
++      }
+       pScsiReq = (SCSIIORequest_t *) mf;
+@@ -1831,8 +1697,8 @@ dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=%
+       /* Use the above information to set up the message frame
+        */
+-      pScsiReq->TargetID = (u8) id;
+-      pScsiReq->Bus = (u8) bus;
++      pScsiReq->TargetID = (u8) target;
++      pScsiReq->Bus = (u8) SCpnt->device->channel;
+       pScsiReq->ChainOffset = 0;
+       pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
+       pScsiReq->CDBLength = SCpnt->cmd_len;
+@@ -1863,7 +1729,7 @@ dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=%
+       pScsiReq->DataLength = cpu_to_le32(datalen);
+       /* SenseBuffer low address */
+-      pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
++      pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
+                                          + (my_idx * MPT_SENSE_BUFFER_ALLOC));
+       /* Now add the SG list
+@@ -1875,39 +1741,67 @@ dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=%
+                       (dma_addr_t) -1);
+       } else {
+               /* Add a 32 or 64 bit SGE */
+-              if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS){
+-                    mptscsih_freeChainBuffers(ioc, my_idx);
+-                    mpt_free_msg_frame(ioc, mf);
++              if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
+                       goto fail;
+-                   }
+       }
+-       SCpnt->host_scribble = (unsigned char *)mf;
+-
+-       if (ioc->bus_type == SPI &&
+-               ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_IN_PROGRESS) {
+-               spin_lock_irqsave(&ioc->PendingMFlock, flags);
+-               ioc->PendingMF = mf;
+-               ioc->PendingSCpnt = SCpnt;
+-               spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-               dpendprintk((KERN_INFO " qcmd: %s: DV In Progress id=%d mf=%p sc=%p into PendingMF\n",
+-                       ioc->name, id, mf, SCpnt));
+-               DBG_DUMP_REQUEST_FRAME(ioc, mf)
+-//             mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
+-               return 0;
+-}
+       hd->ScsiLookup[my_idx] = SCpnt;
++      SCpnt->host_scribble = NULL;
+-      mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
++#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
++      if (hd->ioc->bus_type == SPI) {
++              int dvStatus = hd->ioc->spi_data.dvStatus[target];
++              int issueCmd = 1;
++
++              if (dvStatus || hd->ioc->spi_data.forceDv) {
++
++                      if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
++                              (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
++                              unsigned long lflags;
++                              /* Schedule DV if necessary */
++                              spin_lock_irqsave(&dvtaskQ_lock, lflags);
++                              if (!dvtaskQ_active) {
++                                      dvtaskQ_active = 1;
++                                      spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
++                                      INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
++
++                                      schedule_work(&dvTaskQ_task);
++                              } else {
++                                      spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
++                              }
++                              hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
++                      }
++
++                      /* Trying to do DV to this target, extend timeout.
++                       * Wait to issue until flag is clear
++                       */
++                      if (dvStatus & MPT_SCSICFG_DV_PENDING) {
++                              mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
++                              issueCmd = 0;
++                      }
++
++                      /* Set the DV flags.
++                       */
++                      if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
++                              mptscsih_set_dvflags(hd, pScsiReq);
++
++                      if (!issueCmd)
++                              goto fail;
++              }
++      }
++#endif
++
++      mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
+       dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
+-                      ioc->name, SCpnt, mf, my_idx));
+-      DBG_DUMP_REQUEST_FRAME(ioc,mf)
++                      hd->ioc->name, SCpnt, mf, my_idx));
++      DBG_DUMP_REQUEST_FRAME(mf)
+       return 0;
+  fail:
+-       SCpnt->result = DID_BUS_BUSY << 16;
+-       SCpnt->scsi_done(SCpnt);
+-       return 0;
++      hd->ScsiLookup[my_idx] = NULL;
++      mptscsih_freeChainBuffers(hd->ioc, my_idx);
++      mpt_free_msg_frame(hd->ioc, mf);
++      return SCSI_MLQUEUE_HOST_BUSY;
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -1972,8 +1866,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i
+  *
+  *    @ioc: Pointer to MPT_ADAPTER structure
+  *    @type: Task Management type
+- *    @bus: Logical Bus for reset (if appropriate)
+- *    @id: Logical Target ID for reset (if appropriate)
++ *    @target: Logical Target ID for reset (if appropriate)
+  *    @lun: Logical Unit for reset (if appropriate)
+  *    @ctx2abort: Context for the task to be aborted (if appropriate)
+  *
+@@ -1982,10 +1875,10 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i
+  *    Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
+  *    will be active.
+  *
+- *    Returns 0 for SUCCESS.
++ *    Returns 0 for SUCCESS or -1 if FAILED.
+  */
+ int
+-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 bus, u8 id, u8 lun, int ctx2abort, ulong timeout)
++mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+ {
+       MPT_ADAPTER     *ioc;
+       int              rc = -1;
+@@ -2000,15 +1893,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+               return 0;
+       ioc = hd->ioc;
+-
++      if (ioc == NULL) {
++              printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
++              return FAILED;
++      }
+       dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
+       // SJR - CHECKME - Can we avoid this here?
+       // (mpt_HardResetHandler has this check...)
+       spin_lock_irqsave(&ioc->diagLock, flags);
+- if (ioc->IOCResetInProgress) {
+-     dtmprintk((KERN_INFO MYNAM ": %s: TMHandler failing: "
+-                "IOCResetInProgress\n", ioc->name));
++      if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
+               spin_unlock_irqrestore(&ioc->diagLock, flags);
+               return FAILED;
+       }
+@@ -2023,54 +1917,52 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+               if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
+                       dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
+                          "Timed out waiting for last TM (%d) to complete! \n",
+-                         ioc->name, hd->tmPending));
++                         hd->ioc->name, hd->tmPending));
+                       return FAILED;
+               } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
+                       dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
+                          "Timed out waiting for last TM (%d) to complete! \n",
+-                         ioc->name, hd->tmPending));
++                         hd->ioc->name, hd->tmPending));
+                       return FAILED;
+               } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
+                       dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
+                          "Timed out waiting for last TM (%d) to complete! \n",
+-                         ioc->name, hd->tmPending));
++                         hd->ioc->name, hd->tmPending));
+                       if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
+                               return FAILED;
+                       doTask = 0;
+               }
+       } else {
+-              spin_lock_irqsave(&ioc->FreeQlock, flags);
++              spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+               hd->tmPending |=  (1 << type);
+-              spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++              spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+       }
+       /* Is operational?
+        */
+-      ioc_raw_state = mpt_GetIocState(ioc, 0);
++      ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
+ #ifdef MPT_DEBUG_RESET
+       if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
+               printk(MYIOC_s_WARN_FMT
+                       "TM Handler: IOC Not operational(0x%x)!\n",
+-                ioc->name, ioc_raw_state);
+-               return FAILED;
+-//             panic ( "TMHandler: IOC Not operational!");
++                      hd->ioc->name, ioc_raw_state);
+       }
+ #endif
+       if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
+                               && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
+-              /* Issue the Task Mgmt request.
++              /* Isse the Task Mgmt request.
+                */
+               if (hd->hard_resets < -1)
+                       hd->hard_resets++;
+-              rc = mptscsih_IssueTaskMgmt(hd, type, bus, id, lun, ctx2abort, timeout);
++              rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
+               if (rc) {
+-                      printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", ioc->name);
++                      printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
+               } else {
+-                      dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", ioc->name));
++                      dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
+               }
+       }
+@@ -2079,21 +1971,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+       if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
+               ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
+               dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
+-                       ioc->name));
+-              rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
++                       hd->ioc->name));
++              rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
+       }
+-    /*
+-     * Check IOCStatus from TM reply message
+-     */
+-      if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
+-         hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
+-         hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
+-              rc = 0;
+-      else
+-              rc = FAILED;
+-
+-      dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", ioc->name, rc));
++      dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
+       return rc;
+ }
+@@ -2104,7 +1986,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+  *    mptscsih_IssueTaskMgmt - Generic send Task Management function.
+  *    @hd: Pointer to MPT_SCSI_HOST structure
+  *    @type: Task Management type
+- *    @id: Logical Target ID for reset (if appropriate)
++ *    @target: Logical Target ID for reset (if appropriate)
+  *    @lun: Logical Unit for reset (if appropriate)
+  *    @ctx2abort: Context for the task to be aborted (if appropriate)
+  *
+@@ -2117,31 +1999,28 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8
+  *    else other non-zero value returned.
+  */
+ static int
+-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 bus, u8 id, u8 lun, int ctx2abort, ulong timeout)
++mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+ {
+-      MPT_ADAPTER             *ioc = hd->ioc;
+       MPT_FRAME_HDR   *mf;
+       SCSITaskMgmt_t  *pScsiTm;
+       int              ii;
+       int              retval;
+-      u32              ioc_state;
+-      unsigned long    flags;
+       /* Return Fail to calling function if no message frames available.
+        */
+-      if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
++      if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
+               dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-                  ioc->name,__FUNCTION__));
++                  hd->ioc->name,__FUNCTION__));
+               return FAILED;
+       }
+-      dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt request @ %p\n",
+-                      ioc->name, mf));
++      dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
++                      hd->ioc->name, mf));
+       /* Format the Request
+        */
+       pScsiTm = (SCSITaskMgmt_t *) mf;
+-      pScsiTm->TargetID = id;
+-      pScsiTm->Bus = bus;
++      pScsiTm->TargetID = target;
++      pScsiTm->Bus = channel;
+       pScsiTm->ChainOffset = 0;
+       pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+@@ -2161,52 +2040,31 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd
+       pScsiTm->TaskMsgContext = ctx2abort;
+-      dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
+-                      ioc->name, ctx2abort, type));
++      dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
++                      hd->ioc->name, ctx2abort, type));
+       DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
+-      hd->TM_wait_done = 0;
+-      if ((retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
+-              sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, timeout, CAN_SLEEP)) != 0) {
+-              dfailprintk((MYIOC_s_WARN_FMT "%s: send_handshake FAILED!\n",
+-                      ioc->name, __FUNCTION__));
+-              mpt_free_msg_frame(ioc, mf);
+-
+-              dtmprintk((MYIOC_s_WARN_FMT "Calling mpt_SendIocReset MUR!\n",
+-                      ioc->name));
+-              if ((retval = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) != 0) {
+-                      ioc_state = mpt_GetIocState(ioc, 0);
+-                      dfailprintk((MYIOC_s_WARN_FMT "IOC MUR failed! ioc_state=%08x\n", ioc->name, ioc_state));
+-//                    panic ("IOC MUR Failed");
+-                      ioc->IOCResetInProgress = 0;
++      if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
++              sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
++              CAN_SLEEP)) != 0) {
++              dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
++                      " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
++                      hd->ioc, mf));
++              mpt_free_msg_frame(hd->ioc, mf);
++              return retval;
++      }
+-                      if ((retval = mpt_HardResetHandler(ioc, CAN_SLEEP)) < 0){
+-                              printk((KERN_WARNING " HardResetHandler FAILED!!\n"));                  }
+-                      else {
+-                              dtmprintk((MYIOC_s_WARN_FMT " HardResetHandler succeeded!!\n", ioc->name));
+-                      }
+-              } else {
+-                      dtmprintk((MYIOC_s_WARN_FMT "IOC MUR succeeded\n", ioc->name));
+-                      mptscsih_flush_running_cmds(hd);
+-                      dtmprintk((MYIOC_s_WARN_FMT "Calling do_ioc_recovery! \n", ioc->name));
+-                      if ((retval = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
+-                              dfailprintk((MYIOC_s_ERR_FMT "- (%d) ioc_recovery failed\n", ioc->name, retval));
+-                      } else {
+-                              dtmprintk((MYIOC_s_WARN_FMT "Successful do_ioc_recovery! \n", ioc->name));
+-                      }
+-              }
+-      } else {
+-              dtmprintk((MYIOC_s_WARN_FMT "%s: send_handshake SUCCESS!\n",
+-                      ioc->name, __FUNCTION__));
+-              if (hd->TM_wait_done == 0) {
+-                      wait_event(hd->TM_waitq, hd->TM_wait_done);
+-              }
++      if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
++              dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
++                      " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
++                      hd->ioc, mf));
++              mpt_free_msg_frame(hd->ioc, mf);
++              dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
++                       hd->ioc->name));
++              retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
+       }
+-      spin_lock_irqsave(&ioc->FreeQlock, flags);
+-      hd->tmPending = 0;
+-      hd->tmState = TM_STATE_NONE;
+-      spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++
+       return retval;
+ }
+@@ -2229,8 +2087,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
+       int              scpnt_idx;
+       int              retval;
+       int              tm_timeout;
+-        unsigned long    flags;
+-      unsigned long    sn = SCpnt->serial_number;
+ /* From the 2.6.13 kernels, they have removed calling
+  *    eh_threads with the host_lock in locked state
+@@ -2251,57 +2107,30 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
+       }
+       ioc = hd->ioc;
+-       spin_lock_irqsave(&ioc->diagLock, flags);
+-       if (ioc->IOCResetInProgress) {
+-               dtmprintk((KERN_INFO ": %s: abort: "
+-                          "IOCResetInProgress (sc=%p)\n",
+-                          ioc->name, SCpnt));
+-               spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+-
++      if (hd->resetPending) {
+               return FAILED;
+       }
+-spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+       if (hd->timeouts < -1)
+-
+               hd->timeouts++;
+-       printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
+-              ioc->name, SCpnt);
+-             scsi_print_command(SCpnt);
+-
+-//     printk(KERN_WARNING MYNAM ": %s: Delaying 30 seconds\n", ioc->name);
+-//     mdelay (30000);
+-       /* If this command is pended, then timeout/hang occurred
+-        * during DV. Post command and flush pending Q
+-        * and then following up with the reset request.
+-        */
+-       if ( (mf = mptscsih_search_PendingMF(ioc, SCpnt)) != NULL) {
+-               /* Cmd was in PendingMF.
+-                */
+-               dpendprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
+-                          "Command was in PendingMF! (sc=%p)\n",
+-                          ioc->name, SCpnt));
+-               return SUCCESS;
+-       }
+-
+-
+-
+       /* Find this command
+        */
+       if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
+               /* Cmd not found in ScsiLookup.
+                * Do OS callback.
+                */
+-//            SCpnt->result = DID_RESET << 16;
++              SCpnt->result = DID_RESET << 16;
+               dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
+                          "Command not in the active list! (sc=%p)\n",
+-                         ioc->name, SCpnt));
++                         hd->ioc->name, SCpnt));
+               return SUCCESS;
+       }
++      printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
++             hd->ioc->name, SCpnt);
++      scsi_print_command(SCpnt);
++
+       /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
+        * (the IO to be ABORT'd)
+        *
+@@ -2309,7 +2138,7 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+        *       swap it here either.  It is an opaque cookie to
+        *       the controller, so it does not matter. -DaveM
+        */
+-      mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
++      mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
+       ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
+       hd->abortSCpnt = SCpnt;
+@@ -2318,7 +2147,7 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+       spin_unlock_irq(host_lock);
+ #endif
+       /* set timeout in seconds */
+-      switch (ioc->bus_type) {
++      switch (hd->ioc->bus_type) {
+       case FC:
+               tm_timeout=40;
+               break;
+@@ -2327,7 +2156,7 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+               break;
+       case SPI:
+       default:
+-              tm_timeout=10;
++              tm_timeout=2;
+               break;
+       }
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
+@@ -2337,30 +2166,17 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+       spin_lock_irq(host_lock);
+ #endif
+-if (ioc->bus_type == FC) {
+-      if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
+-          SCpnt->serial_number == sn) {
+-              dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
+-                         "scpnt_idx=%08x sn=%lx (sc=%p)\n",
+-                         ioc->name, scpnt_idx, sn, SCpnt));
+-              retval = FAILED;
+-      }
+-}
+-
+       printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
+-              ioc->name,
++              hd->ioc->name,
+               ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+-       hd->ScsiLookup[scpnt_idx] = NULL;
+-//panic ("Task Abort completed");
+-       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+-       hd->tmPending = 0;
+-       hd->tmState = TM_STATE_NONE;
+-       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+-
+       if (retval == 0)
+               return SUCCESS;
++      if(retval != FAILED ) {
++              hd->tmPending = 0;
++              hd->tmState = TM_STATE_NONE;
++      }
+       return FAILED;
+ }
+@@ -2377,10 +2193,8 @@ int
+ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
+ {
+       MPT_SCSI_HOST   *hd;
+-      MPT_ADAPTER     *ioc;
+-      int             id,retval;
++      int              retval;
+       int              tm_timeout;
+-        unsigned long    flags;
+ /* From the 2.6.13 kernels, they have removed calling
+  *    eh_threads with the host_lock in locked state
+@@ -2398,27 +2212,17 @@ mptscsih_dev_reset(struct scsi_cmnd * SC
+               return FAILED;
+       }
+-       ioc = hd->ioc;
+-       id = SCpnt->device->id;
+-       spin_lock_irqsave(&ioc->diagLock, flags);
+-       if (ioc->IOCResetInProgress) {
+-               dtmprintk((KERN_INFO ": %s: target reset: "
+-                          "IOCResetInProgress (sc=%p)\n",
+-                          ioc->name, SCpnt));
+-               spin_unlock_irqrestore(&ioc->diagLock, flags);
+-
+-            return FAILED;
+-}
+-spin_unlock_irqrestore(&ioc->diagLock, flags);
++      if (hd->resetPending)
++              return FAILED;
+       printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
+-             ioc->name, SCpnt);
++             hd->ioc->name, SCpnt);
+       scsi_print_command(SCpnt);
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+       spin_unlock_irq(host_lock);
+ #endif
+-      switch (ioc->bus_type) {
++      switch (hd->ioc->bus_type) {
+       case FC:
+               tm_timeout=40;
+               break;
+@@ -2427,29 +2231,25 @@ spin_unlock_irqrestore(&ioc->diagLock, f
+               break;
+       case SPI:
+       default:
+-              tm_timeout=10;
++              tm_timeout=5;
+               break;
+       }
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+-      SCpnt->device->channel, id, 0, 0, tm_timeout);
++              SCpnt->device->channel, SCpnt->device->id,
++              0, 0, tm_timeout);
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+       spin_lock_irq(host_lock);
+ #endif
+       printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
+-              ioc->name,
++              hd->ioc->name,
+               ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+-       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+-       hd->tmPending = 0;
+-       hd->tmState = TM_STATE_NONE;
+-       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+-
+-       if (retval == 0) {
+-               if (ioc->bus_type == SPI) {
+-                       dnegoprintk(("writeSDP1: id=%d USE_NVRAM\n",
+-                               id));
+-                       mpt_writeSDP1(ioc, 0, id, MPT_SCSICFG_USE_NVRAM);
+-               }
+-              return SUCCESS;
++
++      if (retval == 0)
++              return SUCCESS;
++
++      if(retval != FAILED ) {
++              hd->tmPending = 0;
++              hd->tmState = TM_STATE_NONE;
+       }
+       return FAILED;
+ }
+@@ -2467,10 +2267,8 @@ int
+ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
+ {
+       MPT_SCSI_HOST   *hd;
+-      MPT_ADAPTER     *ioc;
+       int              retval;
+       int              tm_timeout;
+-        unsigned long    flags;
+ /* From the 2.6.13 kernels, they have removed calling
+  *    eh_threads with the host_lock in locked state
+@@ -2488,9 +2286,8 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
+               return FAILED;
+       }
+-      ioc = hd->ioc;
+       printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
+-             ioc->name, SCpnt);
++             hd->ioc->name, SCpnt);
+       scsi_print_command(SCpnt);
+       if (hd->timeouts < -1)
+@@ -2500,7 +2297,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+       spin_unlock_irq(host_lock);
+ #endif
+-      switch (ioc->bus_type) {
++      switch (hd->ioc->bus_type) {
+       case FC:
+               tm_timeout=40;
+               break;
+@@ -2509,7 +2306,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
+               break;
+       case SPI:
+       default:
+-              tm_timeout=10;
++              tm_timeout=5;
+               break;
+       }
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+@@ -2519,20 +2316,17 @@ mptscsih_bus_reset(struct scsi_cmnd * SC
+ #endif
+       printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
+-              ioc->name,
++              hd->ioc->name,
+               ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+-       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+-       hd->tmPending = 0;
+-       hd->tmState = TM_STATE_NONE;
+-       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+-
+-
+-
+       if (retval == 0)
+               return SUCCESS;
+-        return FAILED;
++      if(retval != FAILED ) {
++              hd->tmPending = 0;
++              hd->tmState = TM_STATE_NONE;
++      }
++      return FAILED;
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -2549,10 +2343,8 @@ int
+ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
+ {
+       MPT_SCSI_HOST *  hd;
+-      MPT_ADAPTER     *ioc;
+       int              status = SUCCESS;
+-        unsigned long    flags;
+-
++      int              can_sleep;
+ /* From the 2.6.13 kernels, they have removed calling
+  *    eh_threads with the host_lock in locked state
+  */
+@@ -2560,6 +2352,8 @@ mptscsih_host_reset(struct scsi_cmnd *SC
+       spinlock_t      *host_lock = SCpnt->device->host->host_lock;
+ #endif
++      can_sleep = crashdump_mode() ? NO_SLEEP : CAN_SLEEP;
++
+       /*  If we can't locate the host to reset, then we failed. */
+       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
+               dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
+@@ -2568,9 +2362,8 @@ mptscsih_host_reset(struct scsi_cmnd *SC
+               return FAILED;
+       }
+-      ioc = hd->ioc;
+       printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
+-             ioc->name, SCpnt);
++             hd->ioc->name, SCpnt);
+       /*  If our attempts to reset the host failed, then return a failed
+        *  status.  The host will be taken off line by the SCSI mid-layer.
+@@ -2578,78 +2371,26 @@ mptscsih_host_reset(struct scsi_cmnd *SC
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+       MPT_HOST_UNLOCK(host_lock);
+ #endif
+-      if (mpt_HardResetHandler(ioc,
+-          crashdump_mode() ? NO_SLEEP : CAN_SLEEP) < 0) {
+-dfailprintk((MYIOC_s_ERR_FMT "host reset: HardResetHandler failed\n", ioc->name));
+-
++      if (mpt_HardResetHandler(hd->ioc, can_sleep) < 0){
+               status = FAILED;
+       } else {
+-
+-dtmprintk((MYIOC_s_ERR_FMT "host reset: HardResetHandler succeeded\n", ioc->name));
+-        status = SUCCESS;
+-
++              /*  Make sure TM pending is cleared and TM state is set to
++               *  NONE.
++               */
++              hd->tmPending = 0;
++              hd->tmState = TM_STATE_NONE;
+       }
+-
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+       MPT_HOST_LOCK(host_lock);
+ #endif
+-       spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+-       hd->tmPending = 0;
+-       hd->tmState = TM_STATE_NONE;
+-       spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+-
+-      return status;
+-}
+-
+-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/* Search the pendingMF for a command with specific index.
+- * If found, delete and return mf pointer
+- * If not found, return NULL
+- */
+-static MPT_FRAME_HDR *
+-mptscsih_search_PendingMF(MPT_ADAPTER *ioc, struct scsi_cmnd * sc)
+-{
+-      MPT_SCSI_HOST   *hd=(MPT_SCSI_HOST *) ioc->sh->hostdata;
+-      MPT_FRAME_HDR   *mf;
+-      unsigned long    flags;
+-      u16              req_idx;
+-      dpendprintk((MYIOC_s_WARN_FMT "%s entered\n",
+-              ioc->name, __FUNCTION__));
+-
+-      spin_lock_irqsave(&ioc->PendingMFlock, flags);
+-      if ((mf=ioc->PendingMF) == NULL) {
+-              spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-              return NULL;
+-      }
++      dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
++                   "Status = %s\n",
++                   (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
+-      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-      if (sc == hd->ScsiLookup[req_idx]) {
+-              ioc->PendingMF = NULL;
+-              spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-
+-              dpendprintk((MYIOC_s_WARN_FMT "%s: found mf=%p\n",
+-                      ioc->name, __FUNCTION__, mf));
+-              DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mf)
+-              /* Free Chain buffers */
+-              mptscsih_freeChainBuffers(ioc, req_idx);
+-              /* Free Message frames */
+-              mpt_free_msg_frame(ioc, mf);
+-              hd->ScsiLookup[req_idx] = NULL;
+-              sc->result = (DID_RESET << 16);
+-              sc->host_scribble = NULL;
+-              sc->scsi_done(sc);      /* Issue the command callback */
+-              dpendprintk(( "%s Executed scsi_done mf=%p sc=%p\n",
+-                      __FUNCTION__, mf, sc));
+-              return mf;
+-      }
+-      spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-      dpendprintk((MYIOC_s_WARN_FMT "%s exiting mf=%p not in ScsiLookup\n",
+-              ioc->name, __FUNCTION__, mf));
+-      return NULL;
++      return status;
+ }
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+  *    mptscsih_tm_pending_wait - wait for pending task management request to
+@@ -2661,21 +2402,20 @@ mptscsih_search_PendingMF(MPT_ADAPTER *i
+ static int
+ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
+ {
+-      MPT_ADAPTER     *ioc = hd->ioc;
+       unsigned long  flags;
+       int            loop_count = 4 * 10;  /* Wait 10 seconds */
+       int            status = FAILED;
+       do {
+-              spin_lock_irqsave(&ioc->FreeQlock, flags);
++              spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+               if (hd->tmState == TM_STATE_NONE) {
+                       hd->tmState = TM_STATE_IN_PROGRESS;
+                       hd->tmPending = 1;
+-                      spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++                      spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+                       status = SUCCESS;
+                       break;
+               }
+-              spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++              spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+               msleep(250);
+       } while (--loop_count);
+@@ -2683,6 +2423,34 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST *
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/**
++ *    mptscsih_tm_wait_for_completion - wait for completion of TM task
++ *    @hd: Pointer to MPT host structure.
++ *
++ *    Returns {SUCCESS,FAILED}.
++ */
++static int
++mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
++{
++      unsigned long  flags;
++      int            loop_count = 4 * timeout;
++      int            status = FAILED;
++
++      do {
++              spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
++              if(hd->tmPending == 0) {
++                      status = SUCCESS;
++                      spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
++                      break;
++              }
++              spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
++              msleep_interruptible(250);
++      } while (--loop_count);
++
++      return status;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ static void
+ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
+ {
+@@ -2720,17 +2488,17 @@ mptscsih_taskmgmt_response_code(MPT_ADAP
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+- *      mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
+- *      @ioc: Pointer to MPT_ADAPTER structure
+- *      @mf: Pointer to SCSI task mgmt request frame
+- *      @mr: Pointer to SCSI task mgmt reply frame
+- *
+- *      This routine is called from mptbase.c::mpt_interrupt() at the completion
+- *      of any SCSI task management request.
+- *      This routine is registered with the MPT (base) driver at driver
+- *      load/init time via the mpt_register() API call.
++ *    mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
++ *    @ioc: Pointer to MPT_ADAPTER structure
++ *    @mf: Pointer to SCSI task mgmt request frame
++ *    @mr: Pointer to SCSI task mgmt reply frame
+  *
+- *      Returns 1 indicating alloc'd request frame ptr should be freed.
++ *    This routine is called from mptbase.c::mpt_interrupt() at the completion
++ *    of any SCSI task management request.
++ *    This routine is registered with the MPT (base) driver at driver
++ *    load/init time via the mpt_register() API call.
++ *
++ *    Returns 1 indicating alloc'd request frame ptr should be freed.
+  */
+ int
+ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
+@@ -2739,26 +2507,27 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *
+       SCSITaskMgmt_t          *pScsiTmReq;
+       MPT_SCSI_HOST           *hd;
+       unsigned long            flags;
+-      u16                      iocstatus = MPI_IOCSTATUS_SUCCESS;
++      u16                      iocstatus;
+       u8                       tmType;
+-      u32                      termination_count;
+       dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
+                       ioc->name, mf, mr));
++      if (ioc->sh) {
+               /* Depending on the thread, a timer is activated for
+                * the TM request.  Delete this timer on completion of TM.
+                * Decrement count of outstanding TM requests.
+                */
+-      hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+-      if (ioc->tmPtr) {
+-              del_timer(&ioc->TMtimer);
+-              mpt_free_msg_frame(ioc, ioc->tmPtr);
+-              ioc->tmPtr = NULL;
++              hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
++      } else {
++              dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
++                      ioc->name));
++              return 1;
+       }
+       if (mr == NULL) {
+-              dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Turbo Reply: Request %p\n",
++              dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
+                       ioc->name, mf));
++              return 1;
+       } else {
+               pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
+               pScsiTmReq = (SCSITaskMgmt_t*)mf;
+@@ -2771,40 +2540,31 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *
+                       mptscsih_taskmgmt_response_code(ioc,
+                           pScsiTmReply->ResponseCode);
+-              termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
+-
+-              iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+-              dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x TerminationCount=%d\n",
+-                      ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo), termination_count));
++              dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
++                              ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
+               DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
++              iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
++              dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
++                      ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
+               /* Error?  (anything non-zero?) */
+               if (iocstatus) {
+                       /* clear flags and continue.
+                        */
+-                      if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
+-                              if (termination_count == 1) {
+-                                      iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
+-                                      dtmprintk((MYIOC_s_WARN_FMT "  SCSI Abort Task IOCStatus is now %04x\n",
+-                                              ioc->name, iocstatus));
+-                              }
++                      if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+                               hd->abortSCpnt = NULL;
+-                      }
+                       /* If an internal command is present
+                        * or the TM failed - reload the FW.
+                        * FC FW may respond FAILED to an ABORT
+                        */
+-                      else if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
++                      if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
+                               if ((hd->cmdPtr) ||
+                                   (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
+                                       if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
+                                               printk((KERN_WARNING
+                                                       " Firmware Reload FAILED!!\n"));
+-                                              dfailprintk((MYIOC_s_ERR_FMT "taskmgmt_complete: HardReset failed\n", ioc->name));
+-                                      } else {
+-                                              dtmprintk((MYIOC_s_ERR_FMT "taskmgmt_complete: HardReset succeeded\n", ioc->name));
+                                       }
+                               }
+                       }
+@@ -2818,16 +2578,12 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *
+       spin_lock_irqsave(&ioc->FreeQlock, flags);
+       hd->tmPending = 0;
+-      hd->tm_iocstatus = iocstatus;
+-      hd->tmState = TM_STATE_NONE;
+       spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++      hd->tmState = TM_STATE_NONE;
+-      hd->TM_wait_done = 1;
+-      wake_up(&hd->TM_waitq);
+       return 1;
+ }
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+  *    This is anyones guess quite frankly.
+@@ -2884,48 +2640,38 @@ mptscsih_slave_alloc(struct scsi_device 
+ {
+       struct Scsi_Host        *host = device->host;
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+-      MPT_ADAPTER             *ioc = hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice              *pTarget;
+-      SpiCfgData             *pSpi;
+-        uint                  bus=device->channel, id=device->id, lun=device->lun;
++      uint                    target = device->id, lun = device->lun;
+       int                     indexed_lun, lun_index;
++      if (hd == NULL)
++              return -ENODEV;
+-      pMptTarget = ioc->Target_List[bus];
+-      pTarget = pMptTarget->Target[id];
+-      dinitprintk((MYIOC_s_INFO_FMT "mptscsih_slave_alloc: bus=%d id=%d lun=%d hd=%p pMptTarget=%p pTarget=%p\n",
+-              ioc->name, bus, id, lun, hd, pMptTarget, pTarget));
+-
+-      if (pTarget) {
+-              dinitprintk((MYIOC_s_ERR_FMT "slave_alloc: pTarget=%p already allocated!\n",
+-                      ioc->name, pTarget));
++      if ((pTarget = hd->Targets[target]))
+               goto out;
+-      }
+       pTarget = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+       if (!pTarget) {
+               printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+-                      ioc->name, sizeof(VirtDevice));
++                              hd->ioc->name, sizeof(VirtDevice));
+               return -ENOMEM;
+       }
++      dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_alloc target=%d lun=%d pTarget=%p\n",
++                      hd->ioc->name, target, lun, pTarget));
+       memset(pTarget, 0, sizeof(VirtDevice));
+-if (ioc->bus_type != SPI)
+-        pTarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+-        pTarget->ioc = ioc;
+-        pTarget->id = id;
+-      pTarget->bus = bus;
++      pTarget->tflags = MPT_TARGET_FLAGS_Q_YES;
++      pTarget->ioc_id = hd->ioc->id;
++      pTarget->target_id = device->id;
++      pTarget->bus_id = device->channel;
+       pTarget->last_lun = MPT_LAST_LUN;
+-      pMptTarget->Target[id] = pTarget;
+-      if (ioc->bus_type == SPI) {
+-               pSpi = &ioc->spi_data;
+-                 pSpi->dvStatus[id] |= (MPT_SCSICFG_NEED_DV |
+-                                         MPT_SCSICFG_DV_NOT_DONE);
+-
+-              if (ioc->raid_data.isRaid & (1 << device->id)) {
++      pTarget->raidVolume = 0;
++      pTarget->device = device;
++      hd->Targets[target] = pTarget;
++      if (hd->ioc->bus_type == SPI) {
++              if (hd->ioc->raid_data.isRaid & (1 << device->id)) {
+                       pTarget->raidVolume = 1;
+-                      ddvprintk((KERN_INFO
++                      ddvtprintk((KERN_INFO
+                           "RAID Volume @ id %d\n", device->id));
+               }
+       }
+@@ -2937,8 +2683,8 @@ out:
+       indexed_lun = (lun % 32);
+       pTarget->luns[lun_index] |= (1 << indexed_lun);
+-      dinitprintk((MYIOC_s_WARN_FMT "mptscsih_slave_alloc: bus=%d id=%d lun=%d pTarget=%p num_luns=%d\n",
+-                      ioc->name, bus, id, lun, pTarget, pTarget->num_luns));
++      dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_alloc target=%d lun=%d pTarget=%p num_luns=%d\n",
++                      hd->ioc->name, target, lun, pTarget, pTarget->num_luns));
+       return 0;
+ }
+@@ -2951,24 +2697,20 @@ mptscsih_slave_destroy(struct scsi_devic
+ {
+       struct Scsi_Host        *host = device->host;
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+-      MPT_ADAPTER             *ioc = hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice              *pTarget;
+-      uint                    bus=device->channel, id=device->id, lun=device->lun;
++      uint                    target = device->id, lun = device->lun;
+       int                     indexed_lun, lun_index;
+-      pMptTarget = ioc->Target_List[bus];
+-      pTarget = pMptTarget->Target[id];
+-      if (pTarget == NULL) {
+-              printk(MYIOC_s_WARN_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p is NULL\n",
+-                      ioc->name, bus, id, lun, pTarget);
++      if ((pTarget = hd->Targets[target]) == NULL) {
++              printk(MYIOC_s_WARN_FMT " mptscsih_slave_destroy target=%d lun=%d pTarget=%p is NULL\n",
++                      hd->ioc->name, target, lun, pTarget);
+               return;
+       }
+-      dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d type=%x pTarget=%p\n",
+-                      ioc->name, bus, id, lun, pTarget->inq_data[0], pTarget));
++      dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d type=%x pTarget=%p\n",
++                      hd->ioc->name, target, lun, pTarget->inq_data[0], pTarget));
+-      if((ioc->bus_type == SPI) &&
+-              mptscsih_is_phys_disk(ioc, bus, id)) {
++      if((hd->ioc->bus_type == SPI) &&
++              mptscsih_is_phys_disk(hd->ioc, target)) {
+       ; /* this target reset shouldn't be issued to hidden
+          * phys disk in a raid volume.  The result would
+          * kill domain validation on that disk; e.g. disk
+@@ -2984,41 +2726,38 @@ mptscsih_slave_destroy(struct scsi_devic
+            */
+       }
+-      mptscsih_search_running_cmds(hd, id, lun);
++      mptscsih_search_running_cmds(hd, target, lun);
+       lun_index = (lun >> 5);  /* 32 luns per lun_index */
+       indexed_lun = (lun % 32);
+       pTarget->luns[lun_index] &= ~(1 << indexed_lun);
+       if (--pTarget->num_luns) {
+-              dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p num_luns=%d luns[0]=%x returning\n",
+-                      ioc->name, bus, id, lun, pTarget, pTarget->num_luns, pTarget->luns[0]));
++              dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d pTarget=%p num_luns=%d luns[0]=%x returning\n",
++                      hd->ioc->name, target, lun, pTarget, pTarget->num_luns, pTarget->luns[0]));
+               return;
+       }
+-      dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d freeing pTarget=%p\n",
+-                      ioc->name, bus, id, lun, pTarget));
+-
+-      if (ioc->bus_type == SPI) {
+-              if (mptscsih_is_phys_disk(ioc, bus, id)) {
+-                      ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
+-    dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy PhysDisk bus=%d id=% d lun=%d pTarget=%p retained\n",ioc->name, bus, id, lun, pTarget));
+-
+-
++      dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d freeing pTarget=%p\n",
++                      hd->ioc->name, target, lun, pTarget));
++      kfree(pTarget);
++      hd->Targets[target] = NULL;
++
++      if (hd->ioc->bus_type == SPI) {
++              if (mptscsih_is_phys_disk(hd->ioc, target)) {
++                      hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
+               } else {
+-                      ioc->spi_data.dvStatus[id] =
+-                (MPT_SCSICFG_NEGOTIATE | MPT_SCSICFG_DV_NOT_DONE);
+-                kfree(pTarget);
+-                pMptTarget->Target[id] = NULL;
+-                dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p completed\n",ioc->name, bus, id, lun, pTarget));
++                      hd->ioc->spi_data.dvStatus[target] =
++                              MPT_SCSICFG_NEGOTIATE;
++                      if (!hd->negoNvram) {
++                              hd->ioc->spi_data.dvStatus[target] |=
++                                      MPT_SCSICFG_DV_NOT_DONE;
++                      }
+               }
+-}else {
+-kfree(pTarget);
+-pMptTarget->Target[id] = NULL;
+-dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p completed\n",
+-ioc->name, bus, id, lun, pTarget));
+-      }
++      }
++      dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d pTarget=%p completed\n",
++                      hd->ioc->name, target, lun, pTarget));
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -3033,34 +2772,29 @@ int
+ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+ {
+       MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+-      MPT_ADAPTER     *ioc = hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice *pTarget;
+       int     max_depth;
+       int     tagged;
+-      pMptTarget = ioc->Target_List[sdev->channel];
+-      pTarget = pMptTarget->Target[sdev->id];
+-      if (pTarget == NULL)
++      if (!(pTarget = hd->Targets[sdev->id]))
+               return 0;
+-
+-       if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
+-               if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+-                       max_depth = 1;
+-               else if (ioc->bus_type == SPI) {
+-                       if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
+-                                (pTarget->minSyncFactor <= MPT_ULTRA160 ))
++      if (hd->ioc->bus_type == SPI) {
++              if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
++                      if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
++                              max_depth = 1;
++                      else if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
++                               (pTarget->minSyncFactor <= MPT_ULTRA160 ))
+                               max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+                       else
+-                      max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
++                              max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
++              } else {
++                      /* error case - No Inq. Data */
++                      max_depth = 1;
++              }
++      } else
++              max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+-               } else
+-                       max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+-       } else {
+-               /* error case - No Inq. Data */
+-               max_depth = 1;
+-       }
+       if (qdepth > max_depth)
+               qdepth = max_depth;
+       if (qdepth == 1)
+@@ -3082,29 +2816,25 @@ int
+ mptscsih_slave_configure(struct scsi_device *device)
+ {
+       struct Scsi_Host        *sh = device->host;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice              *pTarget;
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sh->hostdata;
+-      MPT_ADAPTER             *ioc = hd->ioc;
+       int                     rc;
+-       dinitprintk((MYIOC_s_INFO_FMT
+-               "%s: device @ %p, id=%d, LUN=%d, channel=%d\n",
+-               ioc->name, __FUNCTION__, device, device->id, device->lun,
+-               device->channel));
+-       dinitprintk((MYIOC_s_INFO_FMT
+-                "sdtr %d wdtr %d ppr %d inq length=%d\n",
+-              ioc->name, device->sdtr, device->wdtr,
++      dsprintk((MYIOC_s_INFO_FMT
++              "device @ %p, id=%d, LUN=%d, channel=%d\n",
++              hd->ioc->name, device, device->id, device->lun, device->channel));
++      dsprintk((MYIOC_s_INFO_FMT
++              "sdtr %d wdtr %d ppr %d inq length=%d\n",
++              hd->ioc->name, device->sdtr, device->wdtr,
+               device->ppr, device->inquiry_len));
+-      if (device->id >= ioc->DevicesPerBus) {
++      if (device->id > sh->max_id) {
+               /* error case, should never happen */
+               scsi_adjust_queue_depth(device, 0, 1);
+               goto slave_configure_exit;
+       }
+-      pMptTarget = ioc->Target_List[device->channel];
+-      pTarget = pMptTarget->Target[device->id];
++      pTarget = hd->Targets[device->id];
+       if (pTarget == NULL) {
+               /* Driver doesn't know about this device.
+@@ -3122,19 +2852,19 @@ mptscsih_slave_configure(struct scsi_dev
+               pTarget->configured_lun=1;
+       /* LUN persistancy support */
+-      if (ioc->bus_type == FC) {
++      if (hd->ioc->bus_type == FC) {
+               FCDevicePage0_t fcDevicePage;
+-              rc = mptscsih_readFCDevicePage0(ioc,
+-                  pTarget->bus, pTarget->id, &fcDevicePage);
++              rc = mptscsih_readFCDevicePage0(hd->ioc,
++                  pTarget->bus_id, pTarget->target_id, &fcDevicePage);
+               if (rc > offsetof(FCDevicePage0_t,PortIdentifier)) {
+                       pTarget->WWPN = fcDevicePage.WWPN;
+                       pTarget->WWNN = fcDevicePage.WWNN;
+                       dsprintk((MYIOC_s_INFO_FMT
+-                      "  bus=%d id=%d is WWPN = %08x%08x, WWNN = %08x%08x\n",
+-                              ioc->name, pTarget->bus, pTarget->id,
++                      "  target %d is WWPN = %08x%08x, WWNN = %08x%08x\n",
++                              hd->ioc->name, pTarget->target_id,
+                               le32_to_cpu(fcDevicePage.WWPN.High),
+                               le32_to_cpu(fcDevicePage.WWPN.Low),
+                               le32_to_cpu(fcDevicePage.WWNN.High),
+@@ -3147,19 +2877,19 @@ mptscsih_slave_configure(struct scsi_dev
+               device->inquiry, device->inquiry_len );
+       mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH);
+-      dinitprintk((MYIOC_s_INFO_FMT
++      dsprintk((MYIOC_s_INFO_FMT
+               "Queue depth=%d, tflags=%x\n",
+-              ioc->name, device->queue_depth, pTarget->tflags));
++              hd->ioc->name, device->queue_depth, pTarget->tflags));
+-      dinitprintk((MYIOC_s_INFO_FMT
++      dsprintk((MYIOC_s_INFO_FMT
+               "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
+-              ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
++              hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
+ slave_configure_exit:
+-      dinitprintk((MYIOC_s_INFO_FMT
++      dsprintk((MYIOC_s_INFO_FMT
+               "tagged %d, simple %d, ordered %d\n",
+-              ioc->name,device->tagged_supported, device->simple_tags,
++              hd->ioc->name,device->tagged_supported, device->simple_tags,
+               device->ordered_tags));
+       return 0;
+@@ -3220,20 +2950,16 @@ mptscsih_poll(struct scsi_device *sdev)
+ static void
+ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
+ {
+-      MPT_ADAPTER     *ioc = hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice      *pTarget;
+       SCSIIORequest_t *pReq;
+       u32              sense_count = le32_to_cpu(pScsiReply->SenseCount);
+-      int              bus, id;
++      int              target;
+       /* Get target structure
+        */
+       pReq = (SCSIIORequest_t *) mf;
+-      bus = (int) pReq->Bus;
+-      id = (int) pReq->TargetID;
+-      pMptTarget = ioc->Target_List[bus];
+-      pTarget = pMptTarget->Target[id];
++      target = (int) pReq->TargetID;
++      pTarget = hd->Targets[target];
+       if (sense_count) {
+               u8 *sense_data;
+@@ -3241,15 +2967,15 @@ mptscsih_copy_sense_data(struct scsi_cmn
+               /* Copy the sense received into the scsi command block. */
+               req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-              sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
++              sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
+               memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
+-              DBG_DUMP_SENSE_DATA(sense_data);
+               /* Log SMART data (asc = 0x5D, non-IM case only) if required.
+                */
+-              if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
++              if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
+                       if ((sense_data[12] == 0x5D) && (pTarget->raidVolume == 0)) {
+                               int idx;
++                              MPT_ADAPTER *ioc = hd->ioc;
+                               idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
+                               ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
+@@ -3287,21 +3013,19 @@ mptscsih_copy_sense_data(struct scsi_cmn
+               }
+       } else {
+               dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
+-                              ioc->name));
++                              hd->ioc->name));
+       }
+ }
+-static int
++static u32
+ SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
+ {
+       MPT_SCSI_HOST *hd;
+-      MPT_ADAPTER     *ioc;
+       int i;
+       hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
+-      ioc = hd->ioc;
+-      for (i = 0; i < ioc->req_depth; i++) {
++      for (i = 0; i < hd->ioc->req_depth; i++) {
+               if (hd->ScsiLookup[i] == sc) {
+                       return i;
+               }
+@@ -3315,10 +3039,8 @@ int
+ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+ {
+       MPT_SCSI_HOST   *hd;
+-      struct _MPT_DEVICE      *pMptTarget;
+-      VirtDevice      *pTarget;
+       unsigned long    flags;
+-      int             bus, id, ii;
++      int             ii;
+       int             n;
+       dtmprintk((KERN_INFO MYNAM
+@@ -3338,8 +3060,11 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+       if (reset_phase == MPT_IOC_SETUP_RESET) {
+               dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
+-                mptscsih_flush_running_cmds(hd);
+-                dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Complete\n", ioc->name));
++              /* Clean Up:
++               * 1. Set Hard Reset Pending Flag
++               * All new commands go to doneQ
++               */
++              hd->resetPending = 1;
+       } else if (reset_phase == MPT_IOC_PRE_RESET) {
+               dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
+@@ -3358,41 +3083,28 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+                * free these resources.
+                */
+               if (hd->cmdPtr) {
+-                      del_timer(&hd->InternalCmdTimer);
++                      del_timer(&hd->timer);
+                       mpt_free_msg_frame(ioc, hd->cmdPtr);
+-                        hd->cmdPtr = NULL;
+               }
+-               /* 2d. If a task management has not completed,
+-                * free resources associated with this request.
+-                */
+-               if (ioc->tmPtr) {
+-                       del_timer(&ioc->TMtimer);
+-                       mpt_free_msg_frame(ioc, ioc->tmPtr);
+-                       ioc->tmPtr = NULL;
+-               }
+-               dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
++              dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
+       } else {
+               dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
+               if (ioc->bus_type == FC) {
+                       n = 0;
+-                      for (bus = 0; bus < ioc->NumberOfBuses; bus++) {
+-                              pMptTarget = ioc->Target_List[bus];
+-                              for (id=0; id < ioc->DevicesPerBus; id++) {
+-                                      pTarget = pMptTarget->Target[id];
+-                                      if (pTarget) {
+-                                              dsprintk((MYIOC_s_INFO_FMT
+-                                                      "bus=%d id=%d is known to be WWPN %08x%08x, WWNN %08x%08x\n",
+-                                                      ioc->name, bus, id,
+-                                                      le32_to_cpu(pTarget->WWPN.High),
+-                                                      le32_to_cpu(pTarget->WWPN.Low),
+-                                                      le32_to_cpu(pTarget->WWNN.High),
+-                                                      le32_to_cpu(pTarget->WWNN.Low)));
+-                                              mptscsih_writeFCPortPage3(hd, bus, id);
+-                                              n++;
+-                                      }
++                      for (ii=0; ii < ioc->sh->max_id; ii++) {
++                              if (hd->Targets && hd->Targets[ii]) {
++                                      dsprintk((MYIOC_s_INFO_FMT
++                                              "target %d is known to be WWPN %08x%08x, WWNN %08x%08x\n",
++                                              ioc->name, ii,
++                                              le32_to_cpu(hd->Targets[ii]->WWPN.High),
++                                              le32_to_cpu(hd->Targets[ii]->WWPN.Low),
++                                              le32_to_cpu(hd->Targets[ii]->WWNN.High),
++                                              le32_to_cpu(hd->Targets[ii]->WWNN.Low)));
++                                      mptscsih_writeFCPortPage3(hd, ii);
++                                      n++;
+                               }
+                       }
+@@ -3408,7 +3120,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+               /* ScsiLookup initialization
+                */
+-              for (ii=0; ii < ioc->req_depth; ii++)
++              for (ii=0; ii < hd->ioc->req_depth; ii++)
+                       hd->ScsiLookup[ii] = NULL;
+               /* 2. Chain Buffer initialization
+@@ -3417,19 +3129,17 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+               /* 4. Renegotiate to all devices, if SPI
+                */
+               if (ioc->bus_type == SPI) {
+-                       dnegoprintk((MYIOC_s_WARN_FMT "%s: writeSDP1: ALL_IDS USE_NVRAM\n",
+-                               ioc->name, __FUNCTION__));
+-                       mpt_writeSDP1(ioc, 0, 0, (MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM));
+-
++                      dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
++                      mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
+               }
+               /* 5. Enable new commands to be posted
+                */
+               spin_lock_irqsave(&ioc->FreeQlock, flags);
+               hd->tmPending = 0;
++              spin_unlock_irqrestore(&ioc->FreeQlock, flags);
++              hd->resetPending = 0;
+               hd->tmState = TM_STATE_NONE;
+-                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+-
+               /* 6. If there was an internal command,
+                * wake this process up.
+@@ -3448,9 +3158,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
+               /* 7. Set flag to force DV and re-read IOC Page 3
+                */
+               if (ioc->bus_type == SPI) {
+-ioc->spi_data.forceDv = MPT_SCSICFG_RELOAD_IOC_PG3;
+-ddvprintk(("Set reload IOC Pg3 Flag\n"));
+-
++                      ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
++                      ddvtprintk(("Set reload IOC Pg3 Flag\n"));
+               }
+               dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
+@@ -3468,13 +3177,9 @@ mptscsih_event_process(MPT_ADAPTER *ioc,
+ {
+       MPT_SCSI_HOST *hd;
+       u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+-       struct _MPT_DEVICE      *pMptTarget;
+-       VirtDevice              *pTarget;
+-       int      physDiskNum, bus, id;
+-
+-       devtprintk((MYIOC_s_WARN_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
+-                       ioc->name, event));
++      devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
++                      ioc->name, event));
+       if (ioc->sh == NULL ||
+               ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+@@ -3508,53 +3213,16 @@ mptscsih_event_process(MPT_ADAPTER *ioc,
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+       case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
+       {
++              pMpiEventDataRaid_t pRaidEventData =
++                  (pMpiEventDataRaid_t) pEvReply->Data;
+-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+-                pMpiEventDataRaid_t pRaidEventData =
+-                (pMpiEventDataRaid_t) &pEvReply->Data;
+-
+-/* Domain Validation Needed */
++              /* Domain Validation Needed */
+               if (ioc->bus_type == SPI &&
+                       pRaidEventData->ReasonCode ==
+                       MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
+-                         SpiCfgData      *pSpi;
+-                       physDiskNum = pRaidEventData->PhysDiskNum;
+-                       if (ioc->raid_data.pIocPg3) {
+-                               id = ioc->raid_data.pIocPg3->PhysDisk[physDiskNum].PhysDiskID;
+-                               bus = ioc->raid_data.pIocPg3->PhysDisk[physDiskNum].PhysDiskBus;
+-                               pMptTarget = ioc->Target_List[bus];
+-                               pTarget = (VirtDevice *)pMptTarget->Target[id];
+-                               ddvprintk((KERN_WARNING "%s: Raid Event: DV Requested for PhysDiskNum=%d bus=%d id=%d pTarget=%p\n",
+-                                       ioc->name, physDiskNum, bus, id, pTarget));
+-                       } else {
+-                               ddvprintk((KERN_WARNING "%s: Raid Event: DV Requested for PhysDiskNum=%d but raid_data.pIocPg3 is NULL\n",
+-                                       ioc->name, physDiskNum));
+-                               break;
+-                       }
+-                       pSpi = &ioc->spi_data;
+-                       pSpi->dvStatus[id] |= (MPT_SCSICFG_PHYSDISK_DV_ONLY |
+-                                             MPT_SCSICFG_NEED_DV |
+-                                             MPT_SCSICFG_DV_NOT_DONE);
+-
+-                       if (pTarget == NULL) {
+- ddvprintk((KERN_WARNING " Raid Event: DV Requested for PhysDiskNum=%d bus=%d id=%d but pTarget is NULL\n",
+-                                       physDiskNum, bus, id));
+-                               mptscsih_initTarget(hd, bus, id, 0,
+-                                       NULL, 0 );
+-                               pTarget = (VirtDevice *)pMptTarget->Target[id];
+- ddvprintk((KERN_WARNING "%s: Raid Event: DV Requested for PhysDiskNum=%d bus=%d id=%d pTarget%p now\n",
+-                                       ioc->name, physDiskNum, bus, id, pTarget));
+-                       }
+-                       pSpi->forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
+- ddvprintk((KERN_WARNING "%s: Raid Event: Scheduling DV for PhysDiskNum=%d bus=%d id=%d pTarget=%p\n",
+-                               ioc->name, physDiskNum, bus, id, pTarget));
+- INIT_WORK(&pTarget->dvTask, mptscsih_domainValidation, (void *) pTarget);
+-                       schedule_work(&pTarget->dvTask);
+- ddvprintk((KERN_WARNING "%s: Raid Event: DV Scheduled for PhysDiskNum=%d bus=%d id=%d pTarget=%p\n",
+-                               ioc->name, physDiskNum, bus, id, pTarget));
+-#endif
+-      }
++                      mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
++              }
+               break;
+       }
+ #endif
+@@ -3575,8 +3243,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc,
+ /*
+  *    mptscsih_initTarget - Target, LUN alloc/free functionality.
+  *    @hd: Pointer to MPT_SCSI_HOST structure
+- *    @bus: Bus number (?)
+- *    @id: SCSI target id
++ *    @bus_id: Bus number (?)
++ *    @target_id: SCSI target id
+  *    @lun: SCSI LUN id
+  *    @data: Pointer to data
+  *    @dlen: Number of INQUIRY bytes
+@@ -3589,17 +3257,16 @@ mptscsih_event_process(MPT_ADAPTER *ioc,
+  *
+  */
+ static void
+-mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus, int id, u8 lun, char *data, int dlen)
++mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
+ {
+       int             indexed_lun, lun_index;
+       MPT_ADAPTER     *ioc = hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice      *pTarget;
+       SpiCfgData      *pSpi;
+       char            data_56;
+-      dinitprintk((MYIOC_s_WARN_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
+-                      ioc->name, bus, id, lun, hd));
++      dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
++                      ioc->name, bus_id, target_id, lun, hd));
+       /*
+        * If the peripheral qualifier filter is enabled then if the target reports a 0x1
+@@ -3610,71 +3277,29 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
+        * around a bug in th emid-layer in some distributions in which the mid-layer will
+        * continue to try to communicate to the LUN and evntually create a dummy LUN.
+       */
+-      if (hd->mpt_pq_filter && dlen && (data[0] & 0x20))
++      if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
+               data[0] |= 0x40;
+       /* Is LUN supported? If so, upper 2 bits will be 0
+       * in first byte of inquiry data.
+       */
++      if (data[0] & 0xe0)
++              return;
+-        if (dlen && (data[0] & 0xe0))
+-      return;
+-
+-      pMptTarget = ioc->Target_List[bus];
+-      pTarget = pMptTarget->Target[id];
+-       if (pTarget == NULL) {
+-               dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d pTarget is NULL\n"
+-,
+-                       ioc->name, bus, id, lun));
+-               pTarget = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+-               if (!pTarget) {
+-                       printk(MYIOC_s_ERR_FMT "initTarget kmalloc(%zd) FAILED!\n",
+-                               ioc->name, sizeof(VirtDevice));
+-                       return;
+-               }
+-
+-               memset(pTarget, 0, sizeof(VirtDevice));
+-               if (ioc->bus_type != SPI)
+-                       pTarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+-               pTarget->ioc = ioc;
+-               pTarget->id = id;
+-               pTarget->bus = bus;
+-               pTarget->last_lun = MPT_LAST_LUN;
+-               pTarget->raidVolume = 0;
+-               pMptTarget->Target[id] = pTarget;
+-               if (ioc->bus_type == SPI) {
+-                       if (ioc->raid_data.isRaid & (1 << id)) {
+-                               pTarget->raidVolume = 1;
+-                               ddvprintk((KERN_INFO
+-                                   "RAID Volume @ id %d\n", id));
+-                       }
+-               }
+-
++      if ((pTarget = hd->Targets[target_id]) == NULL) {
+               return;
+-}
+-      dinitprintk((MYIOC_s_WARN_FMT "initTarget bus=%d id=%d lun=%d pTarget=%p\n",
+-                      ioc->name, bus, id, lun, pTarget));
+-       pSpi = &ioc->spi_data;
+-       pTarget->ioc = ioc;
+-       pTarget->tflags &= ~MPT_TARGET_FLAGS_DELETED;
++      }
+       lun_index = (lun >> 5);  /* 32 luns per lun_index */
+       indexed_lun = (lun % 32);
+       pTarget->luns[lun_index] |= (1 << indexed_lun);
+-      if (!(pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
+-              if ( dlen > 8 ) {
+-                      memcpy (pTarget->inq_data, data, 8);
+-              } else {
+-                      memcpy (pTarget->inq_data, data, dlen);
+-              }
+-      }
+       if (ioc->bus_type == SPI) {
+               if ((data[0] == TYPE_PROCESSOR) && (ioc->spi_data.Saf_Te)) {
+                       /* Treat all Processors as SAF-TE if
+                        * command line option is set */
+                       pTarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+-                      mptscsih_writeIOCPage4(hd, id, bus);
++                      mptscsih_writeIOCPage4(hd, target_id, bus_id);
+               }else if ((data[0] == TYPE_PROCESSOR) &&
+                       !(pTarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+                       if ( dlen > 49 ) {
+@@ -3686,17 +3311,29 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
+                                    data[48] == 'T' &&
+                                    data[49] == 'E' ) {
+                                       pTarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+-                                      mptscsih_writeIOCPage4(hd, id, bus);
++                                      mptscsih_writeIOCPage4(hd, target_id, bus_id);
+                               }
+                       }
+               }
+-data_56 = 0x00;  /* Default to no Ultra 160 or 320 capabilities if Inq data length is < 57 */
+-
+-
+               if (!(pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
++                      if ( dlen > 8 ) {
++                              memcpy (pTarget->inq_data, data, 8);
++                      } else {
++                              memcpy (pTarget->inq_data, data, dlen);
++                      }
++
++                      /* If have not done DV, set the DV flag.
++                       */
++                      pSpi = &ioc->spi_data;
++                      if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
++                              if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
++                                      pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
++                      }
+                       pTarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
++
++                      data_56 = 0x00;  /* Default to no Ultra 160 or 320 capabilities if Inq data length is < 57 */
+                       if (dlen > 56) {
+                               if ( (!(pTarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+                               /* Update the target capabilities
+@@ -3705,6 +3342,7 @@ data_56 = 0x00;  /* Default to no Ultra 
+                                       pTarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
+                               }
+                       }
++                      mptscsih_setTargetNegoParms(hd, pTarget, data_56);
+               } else {
+                       /* Initial Inquiry may not request enough data bytes to
+                        * obtain byte 57.  DV will; if target doesn't return
+@@ -3715,40 +3353,25 @@ data_56 = 0x00;  /* Default to no Ultra 
+                                */
+                                       data_56 = data[56];
+                                       pTarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
++                                      mptscsih_setTargetNegoParms(hd, pTarget, data_56);
+                               }
+                       }
+               }
+-
+-mptscsih_setTargetNegoParms(hd, pTarget, data_56);
+-if (pSpi->dvStatus[id] & MPT_SCSICFG_NEED_DV) {
+-       ddvprintk((MYIOC_s_WARN_FMT "%s: DV Scheduled for non-PhysDisk id %d\n",
+-                 ioc->name, __FUNCTION__, id));
+-INIT_WORK(&pTarget->dvTask, mptscsih_domainValidation, (void *) pTarget);
+-schedule_work(&pTarget->dvTask);
+-       }
+-       } else {
+-         pTarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+-         if (ioc->bus_type == SAS) {
+-            if ( (pTarget->inq_data[7] & 0x02) == 0) {
+-                 pTarget->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+-                     }
+-            if ((data[0] == TYPE_TAPE)) {
+-                      if (ioc->facts.IOCCapabilities &
+-                               MPI_IOCFACTS_CAPABILITY_TLR ) {
+-                      if ((pTarget->tflags & MPT_TARGET_FLAGS_TLR_DONE) == 0){
+-                                               if ( data[8]  == 'H' &&
+-                                                    data[9]  == 'P' &&
+-                                                    data[10] == ' ' &&
+-                                                    data[11] == ' ' &&
+-                                                    data[12] == ' ' &&
+-                                                    data[13] == ' ' &&
+-                                                    data[14] == ' ' &&
+-                                                    data[15] == ' ' ) {
+-                                                       mpt_IssueTLR(hd, pTarget);
+-                                                  pTarget->tflags |= MPT_TARGET_FLAGS_TLR_DONE;
+-
+-                                                }
+-
++      } else if (ioc->bus_type == SAS) {
++              if ((data[0] == TYPE_TAPE)) {
++                      if (ioc->facts.IOCCapabilities & 
++                              MPI_IOCFACTS_CAPABILITY_TLR ) {
++                              if ((pTarget->tflags & MPT_TARGET_FLAGS_TLR_DONE) == 0) {
++                                      if ( data[8]  == 'H' &&
++                                           data[9]  == 'P' &&
++                                           data[10] == ' ' &&
++                                           data[11] == ' ' &&
++                                           data[12] == ' ' &&
++                                           data[13] == ' ' &&
++                                           data[14] == ' ' &&
++                                           data[15] == ' ' ) {
++                                              mpt_IssueTLR(hd, pTarget);
++                                              pTarget->tflags |= MPT_TARGET_FLAGS_TLR_DONE;
+                                       }
+                               }
+                       }
+@@ -3760,12 +3383,11 @@ schedule_work(&pTarget->dvTask);
+ static void
+ mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevice *pTarget)
+ {
+-      MPT_ADAPTER             *ioc = hd->ioc;
+       INTERNAL_CMD             iocmd;
+       int                      lun, indexed_lun, lun_index;
+-      iocmd.id = pTarget->id;
+-      iocmd.bus = pTarget->bus;
++      iocmd.id = pTarget->target_id;
++      iocmd.bus = pTarget->bus_id;
+       for (lun=0; lun <= MPT_LAST_LUN; lun++) {
+               /* If LUN present, issue the command
+                */
+@@ -3777,7 +3399,7 @@ mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevi
+               }
+       }
+       printk(MYIOC_s_INFO_FMT "mpt_IssueTLR: Unable find a lun on id=%d\n",
+-              ioc->name, iocmd.id);
++              hd->ioc->name, iocmd.id);
+       return;
+ issueTLR:
+       iocmd.flags = 0;
+@@ -3790,7 +3412,7 @@ issueTLR:
+       if (mptscsih_do_cmd(hd, &iocmd) < 0) {
+               if (mptscsih_do_cmd(hd, &iocmd) < 0) {
+                       printk(MYIOC_s_INFO_FMT "Unable to set TLR on id=%d\n",
+-                              ioc->name, iocmd.id);
++                              hd->ioc->name, iocmd.id);
+               }
+       }
+ }
+@@ -3802,14 +3424,12 @@ issueTLR:
+  *
+  */
+ static void
+-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *pTarget, char byte56)
++mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
+ {
+-      MPT_ADAPTER     *ioc = hd->ioc;
+-      SpiCfgData *pspi_data = &ioc->spi_data;
+-      int  id = (int) pTarget->id;
++      SpiCfgData *pspi_data = &hd->ioc->spi_data;
++      int  id = (int) target->target_id;
+       int  nvram;
+-      struct _MPT_DEVICE      *pMptTarget;
+-      VirtDevice      *loop_pTarget;
++      VirtDevice      *pTarget;
+       int ii;
+       u8 width = MPT_NARROW;
+       u8 factor = MPT_ASYNC;
+@@ -3817,36 +3437,31 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOS
+       u8 version, nfactor;
+       u8 noQas = 1;
+-      pTarget->negoFlags = pspi_data->noQas;
+-ddvprintk((KERN_INFO "Command-line QAS setting sets noQas=%02x on id=%d!\n",
+-               pspi_data->noQas, id));
++      target->negoFlags = pspi_data->noQas;
+-/* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
++      ddvtprintk((KERN_INFO "Command-line QAS setting sets noQas=%02x on id=%d!\n", 
++              pspi_data->noQas, id));
++      /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
+        * support. If available, default QAS to off and allow enabling.
+        * If not available, default QAS to on, turn off for non-disks.
+        */
+       /* Set flags based on Inquiry data
+        */
+-      version = pTarget->inq_data[2] & 0x07;
++      version = target->inq_data[2] & 0x07;
+       if (version < 2) {
+               width = 0;
+               factor = MPT_ULTRA2;
+               offset = pspi_data->maxSyncOffset;
+-              pTarget->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
++              target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+       } else {
+-              if (pTarget->inq_data[7] & 0x20) {
++              if (target->inq_data[7] & 0x20) {
+                       width = 1;
+               }
+-               if (pTarget->inq_data[7] & 0x02)
+-                       pTarget->tflags |= MPT_TARGET_FLAGS_Q_YES;
+-               else
+-                       pTarget->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+-
+-              if (pTarget->inq_data[7] & 0x10) {
++              if (target->inq_data[7] & 0x10) {
+                       factor = pspi_data->minSyncFactor;
+-                      if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_56) {
++                      if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
+                               /* bits 2 & 3 show Clocking support */
+                               if ((byte56 & 0x0C) == 0)
+                                       factor = MPT_ULTRA2;
+@@ -3857,17 +3472,17 @@ ddvprintk((KERN_INFO "Command-line QAS s
+                                               factor = MPT_ULTRA320;
+                                               if (byte56 & 0x02)
+                                               {
+-                                                   ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
++                                                      ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
+                                                       noQas = 0;
+                                               }
+-                                              if (pTarget->inq_data[0] == TYPE_TAPE) {
++                                              if (target->inq_data[0] == TYPE_TAPE) {
+                                                       if (byte56 & 0x01)
+-                                                              pTarget->negoFlags |= MPT_TAPE_NEGO_IDP;
++                                                              target->negoFlags |= MPT_TAPE_NEGO_IDP;
+                                               }
+                                       }
+                               }
+                       } else {
+-                              ddvprintk((KERN_INFO "Ultra 80 on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
++                              ddvtprintk((KERN_INFO "Ultra 80 on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
+                               factor = MPT_ULTRA2;
+                       }
+@@ -3879,7 +3494,7 @@ ddvprintk((KERN_INFO "Command-line QAS s
+                        * bit 1 QAS support, non-raid only
+                        * bit 0 IU support
+                        */
+-                      if (pTarget->raidVolume == 1) {
++                      if (target->raidVolume == 1) {
+                               noQas = 0;
+                       }
+               } else {
+@@ -3888,6 +3503,9 @@ ddvprintk((KERN_INFO "Command-line QAS s
+               }
+       }
++      if ( (target->inq_data[7] & 0x02) == 0) {
++              target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
++      }
+       /* Update tflags based on NVRAM settings. (SCSI only)
+        */
+@@ -3926,43 +3544,41 @@ ddvprintk((KERN_INFO "Command-line QAS s
+       /* Save the data to the target structure.
+        */
+-      pTarget->minSyncFactor = factor;
+-      pTarget->maxOffset = offset;
+-      pTarget->maxWidth = width;
++      target->minSyncFactor = factor;
++      target->maxOffset = offset;
++      target->maxWidth = width;
+-      pTarget->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
++      target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
+       /* Disable unused features.
+        */
+       if (!width)
+-              pTarget->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
++              target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+       if (!offset)
+-              pTarget->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
++              target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+       if ( factor > MPT_ULTRA320 )
+               noQas = 0;
+       /* GEM, processor WORKAROUND
+        */
+-      if ((pTarget->inq_data[0] == TYPE_PROCESSOR) || (pTarget->inq_data[0] > 0x08)) {
+-              pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
++      if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
++              target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
+               pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
+       } else {
+               if (noQas && (pspi_data->noQas == 0)) {
+                       pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+-                      pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
++                      target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+                       /* Disable QAS in a mixed configuration case
+                       */
+-ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+-                pMptTarget = ioc->Target_List[0];
++                      ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+                       for (ii = 0; ii < id; ii++) {
+-                              loop_pTarget = pMptTarget->Target[id];
+-                              if ((loop_pTarget)) {
+-                                      loop_pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+-                                        mpt_writeSDP1(ioc, 0, ii, loop_pTarget->negoFlags);
++                              if ( (pTarget = hd->Targets[ii]) ) {
++                                      pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
++                                      mptscsih_writeSDP1(hd, 0, ii, pTarget->negoFlags);
+                               }
+                       }
+               }
+@@ -3970,33 +3586,115 @@ ddvprintk((KERN_INFO "Disabling QAS due 
+       /* Write SDP1 on this I/O to this target */
+       if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
+-              dnegoprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
+-                /* First IO to this device; NEED_DV will cause async/narrow */
+-                mpt_writeSDP1(ioc, 0, id, 0);
++              ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
++              mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
+               pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
+       } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
+-              dnegoprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
+-              mpt_writeSDP1(ioc, 0, id, MPT_SCSICFG_BLK_NEGO);
++              ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
++              mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
+               pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
+       }
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
++ * Else set the NEED_DV flag after Read Capacity Issued (disks)
++ * or Mode Sense (cdroms).
++ *
++ * Tapes, initTarget will set this flag on completion of Inquiry command.
++ * Called only if DV_NOT_DONE flag is set
++ */
++static void
++mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
++{
++      MPT_ADAPTER     *ioc = hd->ioc;
++      u8 cmd;
++      SpiCfgData      *pSpi;
++
++      ddvtprintk((MYIOC_s_NOTE_FMT
++              " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
++              hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
++
++      if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
++              return;
++
++      cmd = pReq->CDB[0];
++
++      if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
++              pSpi = &ioc->spi_data;
++              if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) {
++                      /* Set NEED_DV for all hidden disks
++                       */
++                      Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
++                      int             numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
++
++                      while (numPDisk) {
++                              pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
++                              ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
++                              pPDisk++;
++                              numPDisk--;
++                      }
++              }
++              pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
++              ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
++      }
++}
++
++/* mptscsih_raid_set_dv_flags()
++ *
++ * New or replaced disk. Set DV flag and schedule DV.
++ */
++static void
++mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
++{
++      MPT_ADAPTER     *ioc = hd->ioc;
++      SpiCfgData      *pSpi = &ioc->spi_data;
++      Ioc3PhysDisk_t  *pPDisk;
++      int              numPDisk;
++
++      if (hd->negoNvram != 0)
++              return;
++
++      ddvtprintk(("DV requested for phys disk id %d\n", id));
++      if (ioc->raid_data.pIocPg3) {
++              pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
++              numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
++              while (numPDisk) {
++                      if (id == pPDisk->PhysDiskNum) {
++                              pSpi->dvStatus[pPDisk->PhysDiskID] =
++                                  (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
++                              pSpi->forceDv = MPT_SCSICFG_NEED_DV;
++                              ddvtprintk(("NEED_DV set for phys disk id %d\n",
++                                  pPDisk->PhysDiskID));
++                              break;
++                      }
++                      pPDisk++;
++                      numPDisk--;
++              }
++
++              if (numPDisk == 0) {
++                      /* The physical disk that needs DV was not found
++                       * in the stored IOC Page 3. The driver must reload
++                       * this page. DV routine will set the NEED_DV flag for
++                       * all phys disks that have DV_NOT_DONE set.
++                       */
++                      pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
++                      ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
++              }
++      }
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*
+  * If no Target, bus reset on 1st I/O. Set the flag to
+  * prevent any future negotiations to this device.
+  */
+ static void
+-mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int id)
++mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
+ {
+-      MPT_ADAPTER     *ioc = hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+-      VirtDevice      *pTarget;
+-      pMptTarget = ioc->Target_List[0];
+-      pTarget = pMptTarget->Target[id];
+-      if (pTarget == NULL)
+-              ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
++      if (hd->Targets[target_id] == NULL)
++              hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
+       return;
+ }
+@@ -4006,9 +3704,266 @@ mptscsih_no_negotiate(MPT_SCSI_HOST *hd,
+  *  SCSI Config Page functionality ...
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*    mptscsih_setDevicePage1Flags  - add Requested and Configuration fields flags
++ *    based on width, factor and offset parameters.
++ *    @width: bus width
++ *    @factor: sync factor
++ *    @offset: sync offset
++ *    @requestedPtr: pointer to requested values (updated)
++ *    @configurationPtr: pointer to configuration values (updated)
++ *    @flags: flags to block WDTR or SDTR negotiation
++ *
++ *    Return: None.
++ *
++ *    Remark: Called by writeSDP1 and _dv_params
++ */
++static void
++mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
++{
++      u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
++      u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
++
++      *configurationPtr = 0;
++      *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
++      *requestedPtr |= (offset << 16) | (factor << 8);
++
++      if (width && offset && !nowide && !nosync) {
++              if (factor < MPT_ULTRA160) {
++                      *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
++                      if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
++                              *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
++                      if (flags & MPT_TAPE_NEGO_IDP)
++                              *requestedPtr |= 0x08000000;
++              } else if (factor < MPT_ULTRA2) {
++                      *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
++              }
++      }
++
++      if (nowide)
++              *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
++
++      if (nosync)
++              *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
++
++      return;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++/*    mptscsih_writeSDP1  - write SCSI Device Page 1
++ *    @hd: Pointer to a SCSI Host Strucutre
++ *    @portnum: IOC port number
++ *    @target_id: writeSDP1 for single ID
++ *    @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
++ *
++ *    Return: -EFAULT if read of config page header fails
++ *            or 0 if success.
++ *
++ *    Remark: If a target has been found, the settings from the
++ *            target structure are used, else the device is set
++ *            to async/narrow.
++ *
++ *    Remark: Called during init and after a FW reload.
++ *    Remark: We do not wait for a return, write pages sequentially.
++ */
++static int
++mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
++{
++      MPT_ADAPTER             *ioc = hd->ioc;
++      Config_t                *pReq;
++      SCSIDevicePage1_t       *pData;
++      VirtDevice              *pTarget;
++      MPT_FRAME_HDR           *mf;
++      dma_addr_t               dataDma;
++      u16                      req_idx;
++      u32                      frameOffset;
++      u32                      requested, configuration, flagsLength;
++      int                      ii, nvram;
++      int                      id = 0, maxid = 0;
++      u8                       width;
++      u8                       factor;
++      u8                       offset;
++      u8                       bus = 0;
++      u8                       negoFlags;
++      u8                       maxwidth, maxoffset, maxfactor;
++
++      if (ioc->spi_data.sdp1length == 0)
++              return 0;
++
++      if (flags & MPT_SCSICFG_ALL_IDS) {
++              id = 0;
++              maxid = ioc->sh->max_id - 1;
++      } else if (ioc->sh) {
++              id = target_id;
++              maxid = min_t(int, id, ioc->sh->max_id - 1);
++      }
++
++      for (; id <= maxid; id++) {
++
++              if (id == ioc->pfacts[portnum].PortSCSIID)
++                      continue;
++
++              /* Use NVRAM to get adapter and target maximums
++               * Data over-riden by target structure information, if present
++               */
++              maxwidth = ioc->spi_data.maxBusWidth;
++              maxoffset = ioc->spi_data.maxSyncOffset;
++              maxfactor = ioc->spi_data.minSyncFactor;
++              if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
++                      nvram = ioc->spi_data.nvram[id];
++
++                      if (maxwidth)
++                              maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
++
++                      if (maxoffset > 0) {
++                              maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
++                              if (maxfactor == 0) {
++                                      /* Key for async */
++                                      maxfactor = MPT_ASYNC;
++                                      maxoffset = 0;
++                              } else if (maxfactor < ioc->spi_data.minSyncFactor) {
++                                      maxfactor = ioc->spi_data.minSyncFactor;
++                              }
++                      } else
++                              maxfactor = MPT_ASYNC;
++              }
++
++              /* Set the negotiation flags.
++               */
++              negoFlags = ioc->spi_data.noQas;
++              if (!maxwidth)
++                      negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
++
++              if (!maxoffset)
++                      negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
++
++              if (flags & MPT_SCSICFG_USE_NVRAM) {
++                      width = maxwidth;
++                      factor = maxfactor;
++                      offset = maxoffset;
++              } else {
++                      width = 0;
++                      factor = MPT_ASYNC;
++                      offset = 0;
++                      //negoFlags = 0;
++                      //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
++              }
++
++              /* If id is not a raid volume, get the updated
++               * transmission settings from the target structure.
++               */
++              if ( (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
++                      width = pTarget->maxWidth;
++                      factor = pTarget->minSyncFactor;
++                      offset = pTarget->maxOffset;
++                      negoFlags |= pTarget->negoFlags;
++              }
++
++#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
++              /* Force to async and narrow if DV has not been executed
++               * for this ID
++               */
++              if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
++                      width = 0;
++                      factor = MPT_ASYNC;
++                      offset = 0;
++              }
++#endif
++
++              if (flags & MPT_SCSICFG_BLK_NEGO)
++                      negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
++
++              mptscsih_setDevicePage1Flags(width, factor, offset,
++                                      &requested, &configuration, negoFlags);
++              dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
++                      target_id, width, factor, offset, negoFlags, requested, configuration));
++
++              /* Get a MF for this command.
++               */
++              if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
++                      dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
++                          ioc->name,__FUNCTION__));
++                      return -EAGAIN;
++              }
++
++              ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
++                      hd->ioc->name, mf, id, requested, configuration));
++
++
++              /* Set the request and the data pointers.
++               * Request takes: 36 bytes (32 bit SGE)
++               * SCSI Device Page 1 requires 16 bytes
++               * 40 + 16 <= size of SCSI IO Request = 56 bytes
++               * and MF size >= 64 bytes.
++               * Place data at end of MF.
++               */
++              pReq = (Config_t *)mf;
++
++              req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
++              frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
++
++              pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
++              dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
++
++              /* Complete the request frame (same for all requests).
++               */
++              pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
++              pReq->Reserved = 0;
++              pReq->ChainOffset = 0;
++              pReq->Function = MPI_FUNCTION_CONFIG;
++              pReq->ExtPageLength = 0;
++              pReq->ExtPageType = 0;
++              pReq->MsgFlags = 0;
++              for (ii=0; ii < 8; ii++) {
++                      pReq->Reserved2[ii] = 0;
++              }
++              pReq->Header.PageVersion = ioc->spi_data.sdp1version;
++              pReq->Header.PageLength = ioc->spi_data.sdp1length;
++              pReq->Header.PageNumber = 1;
++              pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
++              pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
++
++              /* Add a SGE to the config request.
++               */
++              flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
++
++              mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
++
++              /* Set up the common data portion
++               */
++              pData->Header.PageVersion = pReq->Header.PageVersion;
++              pData->Header.PageLength = pReq->Header.PageLength;
++              pData->Header.PageNumber = pReq->Header.PageNumber;
++              pData->Header.PageType = pReq->Header.PageType;
++              pData->RequestedParameters = cpu_to_le32(requested);
++              pData->Reserved = 0;
++              pData->Configuration = cpu_to_le32(configuration);
++
++              if ( pTarget ) {
++                      if ( requested & MPI_SCSIDEVPAGE1_RP_IU ) {
++                              pTarget->last_lun = MPT_LAST_LUN;
++                      } else {
++                              pTarget->last_lun = MPT_NON_IU_LAST_LUN;
++                      }
++                      dsprintk((MYIOC_s_INFO_FMT
++                              "writeSDP1: last_lun=%d on id=%d\n",
++                              ioc->name, pTarget->last_lun, id));
++              }
++
++              dprintk((MYIOC_s_INFO_FMT
++                      "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
++                              ioc->name, id, (id | (bus<<8)),
++                              requested, configuration));
++
++              mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
++      }
++
++      return 0;
++}
++
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*    mptscsih_writeIOCPage4  - write IOC Page 4
+  *    @hd: Pointer to a SCSI Host Structure
+- *    @id: write IOC Page4 for this ID & Bus
++ *    @target_id: write IOC Page4 for this ID & Bus
+  *
+  *    Return: -EAGAIN if unable to obtain a Message Frame
+  *            or 0 if success.
+@@ -4016,7 +3971,7 @@ mptscsih_no_negotiate(MPT_SCSI_HOST *hd,
+  *    Remark: We do not wait for a return, write pages sequentially.
+  */
+ static int
+-mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int id, int bus)
++mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
+ {
+       MPT_ADAPTER             *ioc = hd->ioc;
+       Config_t                *pReq;
+@@ -4060,10 +4015,10 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd
+               IOCPage4Ptr = ioc->spi_data.pIocPg4;
+               dataDma = ioc->spi_data.IocPg4_dma;
+               ii = IOCPage4Ptr->ActiveSEP++;
+-      IOCPage4Ptr->SEP[ii].SEPTargetID = id;
++              IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
+               IOCPage4Ptr->SEP[ii].SEPBus = bus;
+               pReq->Header = IOCPage4Ptr->Header;
+-      pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
++      pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
+       /* Add a SGE to the config request.
+        */
+@@ -4074,7 +4029,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd
+       dinitprintk((MYIOC_s_INFO_FMT
+               "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
+-                      ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, bus));
++                      ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
+       mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+@@ -4116,9 +4071,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+       hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+-        del_timer(&hd->InternalCmdTimer);
+-
+-
+       if ((mf == NULL) ||
+           (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
+               printk(MYIOC_s_ERR_FMT
+@@ -4127,18 +4079,19 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+               goto wakeup;
+       }
++      del_timer(&hd->timer);
+       req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+       hd->ScsiLookup[req_idx] = NULL;
+       pReq = (SCSIIORequest_t *) mf;
+       if (mf != hd->cmdPtr) {
+-              printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p,!= cmdPtr=%p, idx=%d)\n",
+-                              ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
++              printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
++                              hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
+       }
+       hd->cmdPtr = NULL;
+-      ddvprintk((MYIOC_s_WARN_FMT "ScanDvComplete mf=%p,mr=%p,idx=%d\n",
+-                      ioc->name, mf, mr, req_idx));
++      ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
++                      hd->ioc->name, mf, mr, req_idx));
+       hd->pLocal = &hd->localReply;
+       hd->pLocal->scsiStatus = 0;
+@@ -4156,9 +4109,10 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+               status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+               scsi_status = pReply->SCSIStatus;
+- ddvprintk((MYIOC_s_WARN_FMT "%s: IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh IOCLogInfo=%08xh\n",
+-                     ioc->name, __FUNCTION__, status, pReply->SCSIState, scsi_status,
+-                     le32_to_cpu(pReply->IOCLogInfo)));
++
++              ddvtprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
++                           status, pReply->SCSIState, scsi_status,
++                           le32_to_cpu(pReply->IOCLogInfo)));
+               switch(status) {
+@@ -4203,14 +4157,13 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+                                */
+                               completionCode = MPT_SCANDV_SENSE;
+                               hd->pLocal->scsiStatus = scsi_status;
+-                              sense_data = ((u8 *)ioc->sense_buf_pool +
++                              sense_data = ((u8 *)hd->ioc->sense_buf_pool +
+                                       (req_idx * MPT_SENSE_BUFFER_ALLOC));
+                               sz = min_t(int, pReq->SenseBufferLength,
+                                                       SCSI_STD_SENSE_BYTES);
+                               memcpy(hd->pLocal->sense, sense_data, sz);
+-                              DBG_DUMP_SENSE_DATA(sense_data);
+                               ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
+                                               sense_data));
+                       } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
+@@ -4224,7 +4177,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+                       else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
+                               completionCode = MPT_SCANDV_DID_RESET;
+                       else if (scsi_status == MPI_SCSI_STATUS_BUSY)
+-                              completionCode = MPT_SCANDV_BUSY;
++                              completionCode = MPT_SCANDV_SOME_ERROR;
+                       else {
+                               completionCode = MPT_SCANDV_GOOD;
+                               hd->pLocal->scsiStatus = scsi_status;
+@@ -4243,9 +4196,9 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
+                       break;
+               }       /* switch(status) */
+-               ddvprintk((MYIOC_s_WARN_FMT ": completionCode=%08xh\n",
+-                       ioc->name, completionCode));
++              ddvtprintk((KERN_NOTICE "  completionCode set to %08xh\n",
++                              completionCode));
+       } /* end of address reply case */
+       hd->pLocal->completion = completionCode;
+@@ -4266,53 +4219,48 @@ wakeup:
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+-/*    mptscsih_InternalCmdTimer_expired - Call back for DV timer process.
++/*    mptscsih_timer_expired - Call back for timer process.
+  *    Used only for dv functionality.
+  *    @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
+  *
+  */
+-void mptscsih_InternalCmdTimer_expired(unsigned long data)
++void
++mptscsih_timer_expired(unsigned long data)
+ {
+       MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
+-      MPT_ADAPTER     *ioc=hd->ioc;
+-      MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
+-      ddvprintk((MYIOC_s_WARN_FMT "InternalCmdTimer_expired! cmdPtr=%p\n",
+-              ioc->name, cmd));
++      ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
+-      hd->cmdPtr = NULL;
+-      if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
+-#ifdef MPT_DEBUG_DV
+-              SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) cmd;
+-              int      id = pScsiReq->TargetID;
+-
+-              /* Desire to issue a task management request here.
+-               * TM requests MUST be single threaded.
+-               * If old eh code and no TM current, issue request.
+-               * If new eh code, do nothing. Wait for OS cmd timeout
+-               *      for bus reset.
+-               */
+-              ddvprintk((MYIOC_s_WARN_FMT "DV Cmd Timeout: id=%d CDB=%02x\n",
+-                      ioc->name, id, pScsiReq->CDB[0]));
+-#endif
++      if (hd->cmdPtr) {
++              MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
+-              /*
+-               * Wake up the original calling thread
+-               */
+-              hd->pLocal = &hd->localReply;
+-              hd->pLocal->completion = MPT_SCANDV_FALLBACK;
+-              hd->scandv_wait_done = 1;
+-              wake_up(&hd->scandv_waitq);
+-      } else {
+-              /* Perform a FW reload */
+-              if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
+-                      printk(MYIOC_s_WARN_FMT "InternalCmdTimer_expired: HardReset FAILED!\n", ioc->name);
+-                      dfailprintk((MYIOC_s_ERR_FMT "InternalCmdTimer_expired: HardReset failed\n", ioc->name));
++              if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
++                      /* Desire to issue a task management request here.
++                       * TM requests MUST be single threaded.
++                       * If old eh code and no TM current, issue request.
++                       * If new eh code, do nothing. Wait for OS cmd timeout
++                       *      for bus reset.
++                       */
++                      ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
+               } else {
+-                      ddvprintk((MYIOC_s_ERR_FMT "InternalCmdTimer_expired: HardReset succeeded\n", ioc->name));
++                      /* Perform a FW reload */
++                      if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
++                              printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
++                      }
+               }
++      } else {
++              /* This should NEVER happen */
++              printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
+       }
+-      ddvprintk((MYIOC_s_WARN_FMT "InternalCmdTimer_expired Complete!\n", ioc->name));
++
++      /* No more processing.
++       * TM call will generate an interrupt for SCSI TM Management.
++       * The FW will reply to all outstanding commands, callback will finish cleanup.
++       * Hard reset clean-up will free all resources.
++       */
++      ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
++
++      return;
+ }
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+@@ -4331,23 +4279,22 @@ void mptscsih_InternalCmdTimer_expired(u
+ static int
+ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
+ {
+-      MPT_ADAPTER             *ioc = hd->ioc;
+       MpiRaidActionRequest_t  *pReq;
+       MPT_FRAME_HDR           *mf;
+       int                     in_isr;
+       in_isr = in_interrupt();
+       if (in_isr) {
+-              dfailprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
+-                              ioc->name));
++              dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
++                                      hd->ioc->name));
+               return -EPERM;
+       }
+       /* Get and Populate a free Frame
+        */
+-      if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
++      if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
+               dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-                  ioc->name,__FUNCTION__));
++                  hd->ioc->name,__FUNCTION__));
+               return -EAGAIN;
+       }
+       pReq = (MpiRaidActionRequest_t *)mf;
+@@ -4367,11 +4314,10 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a
+               MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
+       ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
+-                      ioc->name, action, io->id));
++                      hd->ioc->name, action, io->id));
+       hd->pLocal = NULL;
+-      hd->InternalCmdTimer.data = (unsigned long) hd;
+-        hd->InternalCmdTimer.expires = jiffies + HZ*10; /* 10 second timeout */
++      hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
+       hd->scandv_wait_done = 0;
+       /* Save cmd pointer, for resource free if timeout or
+@@ -4379,8 +4325,8 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a
+        */
+       hd->cmdPtr = mf;
+-      add_timer(&hd->InternalCmdTimer);
+-        mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
++      add_timer(&hd->timer);
++      mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+       wait_event(hd->scandv_waitq, hd->scandv_wait_done);
+       if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
+@@ -4413,7 +4359,6 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a
+ int
+ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
+ {
+-      MPT_ADAPTER     *ioc = hd->ioc;
+       MPT_FRAME_HDR   *mf;
+       SCSIIORequest_t *pScsiReq;
+       SCSIIORequest_t  ReqCopy;
+@@ -4426,8 +4371,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+       in_isr = in_interrupt();
+       if (in_isr) {
+-              dfailprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
+-                              ioc->name));
++              dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
++                                      hd->ioc->name));
+               return -EPERM;
+       }
+@@ -4542,16 +4487,14 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+       default:
+               /* Error Case */
+-              dfailprintk((MYIOC_s_WARN_FMT "%s,Unknown cmd=%02x!!\n",
+-                  ioc->name,__FUNCTION__, cmd));
+               return -EFAULT;
+       }
+       /* Get and Populate a free Frame
+        */
+-      if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
++      if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
+               dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+-                  ioc->name,__FUNCTION__));
++                  hd->ioc->name,__FUNCTION__));
+               return -EBUSY;
+       }
+@@ -4593,18 +4536,18 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+       if (cmd == REQUEST_SENSE) {
+               pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
+               ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
+-                      ioc->name, cmd));
++                      hd->ioc->name, cmd));
+       }
+       for (ii=0; ii < 16; ii++)
+               pScsiReq->CDB[ii] = CDB[ii];
+       pScsiReq->DataLength = cpu_to_le32(io->size);
+-      pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
++      pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
+                                          + (my_idx * MPT_SENSE_BUFFER_ALLOC));
+-       ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d) mf=%p\n",
+-                       ioc->name, cmd, io->bus, io->id, io->lun, pScsiReq));
++      ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
++                      hd->ioc->name, cmd, io->bus, io->id, io->lun));
+       if (dir == MPI_SCSIIO_CONTROL_READ) {
+               mpt_add_sge((char *) &pScsiReq->SGL,
+@@ -4630,8 +4573,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+        *      set scandv_wait_done and call wake_up
+        */
+       hd->pLocal = NULL;
+-        hd->InternalCmdTimer.data = (unsigned long) hd;
+-        hd->InternalCmdTimer.expires = jiffies + HZ*cmdTimeout;
++      hd->timer.expires = jiffies + HZ*cmdTimeout;
+       hd->scandv_wait_done = 0;
+       /* Save cmd pointer, for resource free if timeout or
+@@ -4639,8 +4581,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+        */
+       hd->cmdPtr = mf;
+-        add_timer(&hd->InternalCmdTimer);
+-      mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
++      add_timer(&hd->timer);
++      mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+       wait_event(hd->scandv_waitq, hd->scandv_wait_done);
+       if (hd->pLocal) {
+@@ -4657,7 +4599,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
+               rc = -EFAULT;
+               /* This should never happen. */
+               ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
+-                              ioc->name));
++                              hd->ioc->name));
+       }
+       return rc;
+@@ -4678,7 +4620,6 @@ static int
+ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
+ {
+       MPT_ADAPTER             *ioc= hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice              *pTarget;
+       SCSIDevicePage1_t       *pcfg1Data = NULL;
+       INTERNAL_CMD             iocmd;
+@@ -4690,6 +4631,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+       int                      lun;
+       int                      indexed_lun, lun_index;
+       int                      hostId = ioc->pfacts[portnum].PortSCSIID;
++      int                      max_id;
+       int                      requested, configuration, data;
+       int                      doConfig = 0;
+       u8                       flags, factor;
+@@ -4697,6 +4639,8 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+       dexitprintk((KERN_INFO MYNAM ": %s called\n",
+               __FUNCTION__));
++      max_id = ioc->sh->max_id - 1;
++
+       /* Following parameters will not change
+        * in this routine.
+        */
+@@ -4733,11 +4677,10 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+       /* loop through all devices on this port
+        */
+-      while (bus < ioc->NumberOfBuses) {
++      while (bus < MPT_MAX_BUS) {
+               iocmd.bus = bus;
+               iocmd.id = id;
+-              pMptTarget = ioc->Target_List[bus];
+-              pTarget = pMptTarget->Target[id];
++              pTarget = hd->Targets[(int)id];
+               if (doConfig) {
+@@ -4745,9 +4688,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+                       if (pTarget && !pTarget->raidVolume) {
+                               flags = pTarget->negoFlags;
+                       } else {
+-                              flags = ioc->spi_data.noQas;
+-                              if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+-                                      data = ioc->spi_data.nvram[id];
++                              flags = hd->ioc->spi_data.noQas;
++                              if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
++                                      data = hd->ioc->spi_data.nvram[id];
+                                       if (data & MPT_NVRAM_WIDE_DISABLE)
+                                               flags |= MPT_TARGET_NO_NEGO_WIDE;
+@@ -4759,16 +4702,16 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+                       }
+                       /* Force to async, narrow */
+-                       mpt_setSDP1parameters(0, MPT_ASYNC, 0, flags,
+-                               &requested, &configuration);
+-                       dnegoprintk(("%s: syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+-                                "offset=0 negoFlags=%x requested=%x configuration=%x\n",
+-                                ioc->name, id, flags, requested, configuration));
++                      mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
++                                      &configuration, flags);
++                      dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
++                              "offset=0 negoFlags=%x request=%x config=%x\n",
++                              id, flags, requested, configuration));
+                       pcfg1Data->RequestedParameters = cpu_to_le32(requested);
+                       pcfg1Data->Reserved = 0;
+                       pcfg1Data->Configuration = cpu_to_le32(configuration);
+                       cfg.pageAddr = (bus<<8) | id;
+-                      mpt_config(ioc, &cfg);
++                      mpt_config(hd->ioc, &cfg);
+               }
+               /* If target Ptr NULL or if this target is NOT a disk, skip.
+@@ -4780,9 +4723,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+                               lun_index = (lun >> 5);  /* 32 luns per lun_index */
+                               indexed_lun = (lun % 32);
+                               if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
+-                                      dexitprintk((KERN_INFO MYNAM ": %s: synchronize_cache for bus=%d id=%d lun=%d\n",
+-                                              ioc->name, bus, id, lun));
+-
+                                       iocmd.lun = lun;
+                                       (void) mptscsih_do_cmd(hd, &iocmd);
+                               }
+@@ -4795,27 +4735,21 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+               if (id == hostId)
+                       id++;
+-              if (id >= ioc->DevicesPerBus) {
++              if (id > max_id) {
+                       id = 0;
+                       bus++;
+               }
+       }
+-      dexitprintk((KERN_INFO MYNAM ": %s: synchronize_cache commands done\n",
+-              ioc->name));
+-
+       if (pcfg1Data) {
+-              dexitprintk((KERN_INFO MYNAM ": %s: free pcfg1Data=%p\n",
+-                      ioc->name, pcfg1Data));
+               pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
+       }
+-      dexitprintk((KERN_INFO MYNAM ": %s: synchronize_cache done\n",
+-              ioc->name));
+       return 0;
+ }
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /**
+  *    mptscsih_domainValidation - Top level handler for domain validation.
+  *    @hd: Pointer to MPT_SCSI_HOST structure.
+@@ -4829,209 +4763,163 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
+ static void
+ mptscsih_domainValidation(void *arg)
+ {
+-      VirtDevice      *pTarget=(VirtDevice *)arg;
+-      MPT_SCSI_HOST   *hd;
+-      MPT_ADAPTER     *ioc;
+-      unsigned long    flags;
+-      int              id, dvStatus;
+-      int              ii;
++      MPT_SCSI_HOST           *hd;
++      MPT_ADAPTER             *ioc;
++      unsigned long            flags;
++      int                      id, maxid, dvStatus, did;
++      int                      ii, isPhysDisk;
+       spin_lock_irqsave(&dvtaskQ_lock, flags);
+       dvtaskQ_active = 1;
++      if (dvtaskQ_release) {
++              dvtaskQ_active = 0;
++              spin_unlock_irqrestore(&dvtaskQ_lock, flags);
++              return;
++      }
+       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
+-      if (pTarget == NULL) {
+-              ddvprintk((KERN_WARNING "domainValidation called with NULL pTarget\n"));
+-              goto mptscsih_domainValidation_exit;
+-      }
+-      id = pTarget->id;
+-      ioc = pTarget->ioc;
+-      if (ioc == NULL) {
+-              ddvprintk((KERN_WARNING "domainValidation called with NULL pTarget->ioc id=%d\n", id));
+-              goto mptscsih_domainValidation_exit;
+-      }
+-//    set_current_state(TASK_INTERRUPTIBLE);
+-//    schedule_timeout(MPT_HZ/4);
++      if (crashdump_mode())
++              return;
+-      hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
++      /* For this ioc, loop through all devices and do dv to each device.
++       * When complete with this ioc, search through the ioc list, and
++       * for each scsi ioc found, do dv for all devices. Exit when no
++       * device needs dv.
++       */
++      did = 1;
++      while (did) {
++              did = 0;
++              list_for_each_entry(ioc, &ioc_list, list) {
++                      spin_lock_irqsave(&dvtaskQ_lock, flags);
++                      if (dvtaskQ_release) {
++                              dvtaskQ_active = 0;
++                              spin_unlock_irqrestore(&dvtaskQ_lock, flags);
++                              return;
++                      }
++                      spin_unlock_irqrestore(&dvtaskQ_lock, flags);
+-      ddvprintk((KERN_WARNING "domainValidation pTarget=%p ioc=%p hd=%p id=%d\n",
+-              pTarget, ioc, hd, id));
+-      if (hd == NULL) {
+-              ddvprintk((KERN_WARNING "domainValidation called with NULL hd id=%d\n", id));
+-              goto mptscsih_domainValidation_exit;
+-      }
++                      msleep(250);
+-      if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
+-              mpt_read_ioc_pg_3(ioc);
+-              if (ioc->spi_data.dvStatus[id] & MPT_SCSICFG_PHYSDISK_DV_ONLY) {
+-                      ddvprintk((KERN_WARNING "PHYSDISK_DV_ONLY id=%d\n", id));
+-                      ioc->spi_data.dvStatus[id] &=
+-                              ~MPT_SCSICFG_PHYSDISK_DV_ONLY;
+-                      if (mptscsih_doDv(hd, 0, id) == 1) {
+-                              /* Untagged device was busy, try again
+-                               */
+-                              ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
+-                      } else {
+-                              /* DV is complete. Clear flags.
+-                               */
+-                              ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
+-                      }
+-                      goto mptscsih_domainValidation_exit;
+-              }
++                      /* DV only to SPI adapters */
++                      if (ioc->bus_type != SPI)
++                              continue;
+-              if (ioc->raid_data.pIocPg3) {
+-                      Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
+-                      int     numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
++                      /* Make sure everything looks ok */
++                      if (ioc->sh == NULL)
++                              continue;
+-                      while (numPDisk) {
+-                              if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
+-                                      ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
++                      hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
++                      if (hd == NULL)
++                              continue;
+-                              pPDisk++;
+-                              numPDisk--;
++                      if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
++                              mpt_read_ioc_pg_3(ioc);
++                              if (ioc->raid_data.pIocPg3) {
++                                      Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
++                                      int             numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
++
++                                      while (numPDisk) {
++                                              if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
++                                                      ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
++
++                                              pPDisk++;
++                                              numPDisk--;
++                                      }
++                              }
++                              ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
+                       }
+-              }
+-              ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
+-      }
+-      dvStatus = ioc->spi_data.dvStatus[id];
++                      maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
+-      if (dvStatus & MPT_SCSICFG_NEED_DV) {
+-              ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_IN_PROGRESS;
+-              ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
++                      for (id = 0; id < maxid; id++) {
++                              spin_lock_irqsave(&dvtaskQ_lock, flags);
++                              if (dvtaskQ_release) {
++                                      dvtaskQ_active = 0;
++                                      spin_unlock_irqrestore(&dvtaskQ_lock, flags);
++                                      return;
++                              }
++                              spin_unlock_irqrestore(&dvtaskQ_lock, flags);
++                              dvStatus = hd->ioc->spi_data.dvStatus[id];
+-//            set_current_state(TASK_INTERRUPTIBLE);
+-//            schedule_timeout(MPT_HZ/4);
++                              if (dvStatus & MPT_SCSICFG_NEED_DV) {
++                                      did++;
++                                      hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
++                                      hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
++
++                                      msleep(250);
++
++                                      /* If hidden phys disk, block IO's to all
++                                       *      raid volumes
++                                       * else, process normally
++                                       */
++                                      isPhysDisk = mptscsih_is_phys_disk(hd->ioc, id);
++                                      if (isPhysDisk) {
++                                              for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
++                                                      if (hd->ioc->raid_data.isRaid & (1 << ii)) {
++                                                              hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
++                                                      }
++                                              }
++                                      }
+-              /* If hidden phys disk, block IO's to all
+-               *      raid volumes
+-               * else, process normally
+-               */
+-              if (ioc->raid_data.isRaid & (1 << id)) {
+-                      Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
+-                      int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+-                      while (numPDisk) {
+-                              ii = pPDisk->PhysDiskID;
+-                              if ( ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) {
+-                                      ddvprintk((KERN_WARNING "doDv for PhysDiskNum=%d PhysDiskID=%d numPDisk=%d\n",
+-                                              pPDisk->PhysDiskNum, ii, numPDisk));
+-                                      if (mptscsih_doDv(hd, 0, ii) == 1) {
++                                      if(mpt_alt_ioc_wait(hd->ioc)!=0) {
++                                              ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n",
++                                                  hd->ioc->name));
++                                              continue;
++                                      }
++
++                                      if (mptscsih_doDv(hd, 0, id) == 1) {
+                                               /* Untagged device was busy, try again
+                                                */
+-                                              ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
++                                              hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
++                                              hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
+                                       } else {
+-                                              ddvprintk((KERN_WARNING "doDv successful for PhysDiskNum=%d PhysDiskID=%d\n",
+-                                                      pPDisk->PhysDiskNum, ii));
+                                               /* DV is complete. Clear flags.
+                                                */
+-                                              ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_NOT_DONE;
++                                              hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
++                                      }
++
++                                      spin_lock(&hd->ioc->initializing_hba_lock);
++                                      hd->ioc->initializing_hba_lock_flag=0;
++                                      spin_unlock(&hd->ioc->initializing_hba_lock);
++
++                                      if (isPhysDisk) {
++                                              for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
++                                                      if (hd->ioc->raid_data.isRaid & (1 << ii)) {
++                                                              hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
++                                                      }
++                                              }
+                                       }
++
++                                      if (hd->ioc->spi_data.noQas)
++                                              mptscsih_qas_check(hd, id);
+                               }
+-                              pPDisk++;
+-                              numPDisk--;
+-                      }
+-              } else {
+-                      ddvprintk((KERN_WARNING "doDv for id=%d\n",
+-                              id));
+-                      if (mptscsih_doDv(hd, 0, id) == 1) {
+-                              /* Untagged device was busy, try again
+-                               */
+-                              ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
+-                      } else {
+-                              ddvprintk((KERN_WARNING "doDv successful for id=%d\n",
+-                                      id));
+-                              /* DV is complete. Clear flags.
+-                               */
+-                              ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
+                       }
+               }
+-
+-              if (ioc->spi_data.noQas)
+-                      mptscsih_qas_check(hd, id);
+-      } else {
+-              ddvprintk((KERN_INFO "~NEED_DV dvStatus=%x for id %d\n",
+-                      dvStatus, id));
+-//            panic( "~NEED_DV");
+       }
+-mptscsih_domainValidation_exit:
++
+       spin_lock_irqsave(&dvtaskQ_lock, flags);
+       dvtaskQ_active = 0;
+       spin_unlock_irqrestore(&dvtaskQ_lock, flags);
+-}
+-
+-/* Post command on the PendingMF to the FW.
+- */
+-void
+-mptscsih_post_PendingMF_command(MPT_ADAPTER *ioc)
+-{
+-      MPT_SCSI_HOST   *hd;
+-      MPT_FRAME_HDR   *mf;
+-      struct scsi_cmnd *SCpnt;
+-      unsigned long    flags;
+-      u16              req_idx;
+-
+-      spin_lock_irqsave(&ioc->PendingMFlock, flags);
+-      if ((mf=ioc->PendingMF) == NULL) {
+-              spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-              dpendprintk((MYIOC_s_INFO_FMT "%s: PendingMF is empty\n",
+-                      ioc->name, __FUNCTION__));
+-              return;
+-      }
+-
+-      mf = ioc->PendingMF;
+-      SCpnt = ioc->PendingSCpnt;
+-      ioc->PendingMF = NULL;
+-      spin_unlock_irqrestore(&ioc->PendingMFlock, flags);
+-
+-      dpendprintk((MYIOC_s_INFO_FMT "mptscsih_post_PendingMF_command: mf=%p\n",
+-              ioc->name, mf));
+-      DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mf)
+-
+-      hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+-      req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+-      hd->ScsiLookup[req_idx] = SCpnt;
+-      mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
++      return;
+ }
+-
+ /* Search IOC page 3 to determine if this is hidden physical disk
+  */
+ static int
+-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id)
++mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+ {
+-      struct inactive_raid_component_info *component_info;
+       int i;
+-      int rc = 0;
+-
+-      if (!ioc->raid_data.pIocPg3)
+-              goto out;
+-      for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+-              if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+-                  (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+-                      rc = 1;
+-                      goto out;
+-              }
+-      }
+-      /*
+-       * Check inactive list for matching phys disks
+-       */
+-      if (list_empty(&ioc->raid_data.inactive_list))
+-              goto out;
++      if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
++              return 0;
+-      down(&ioc->raid_data.inactive_list_mutex);
+-      list_for_each_entry(component_info,
+-          &ioc->raid_data.inactive_list, list) {
+-              if ((component_info->d.PhysDiskID == id) &&
+-                  (component_info->d.PhysDiskBus == channel))
+-                      rc = 1;
++      for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
++              if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
++                      return 1;
+       }
+-      up(&ioc->raid_data.inactive_list_mutex);
+- out:
+-      return rc;
++      return 0;
+ }
+ /* Write SDP1 if no QAS has been enabled
+@@ -5039,37 +4927,32 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, 
+ static void
+ mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
+ {
+-      MPT_ADAPTER     *ioc = hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice *pTarget;
+       int ii;
+-      pMptTarget = ioc->Target_List[0];
+       for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+               if (ii == id)
+                       continue;
+-              if ((ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
++              if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
+                       continue;
+-              pTarget = pMptTarget->Target[ii];
+-
+-              if (pTarget) {
+-                      if (!pTarget->raidVolume) {
+-                              if ((pTarget->negoFlags & ioc->spi_data.noQas) == 0) {
+-                                      pTarget->negoFlags |= ioc->spi_data.noQas;
+-                                      dnegoprintk(("mptscsih_qas_check: writeSDP1: id=%d negoFlags=%d\n", ii, pTarget->negoFlags));
+-                    mpt_writeSDP1(ioc, 0, ii, MPT_SCSICFG_USE_NVRAM);
+-                                              }
+-                      } else {
+-                              if (mptscsih_is_phys_disk(ioc, 0, ii) == 1) {
+-                                      dnegoprintk(("mptscsih_qas_check: is_phys_disk writeSDP1: id=%d SCSICFG_USE_NVRAM\n", ii));
+-                                    mpt_writeSDP1(ioc, 0, ii, MPT_SCSICFG_USE_NVRAM);
++              pTarget = hd->Targets[ii];
+-                              }
++              if (pTarget && (!pTarget->raidVolume)) {
++                      if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
++                              pTarget->negoFlags |= hd->ioc->spi_data.noQas;
++                              dnegoprintk(("writeSDP1: id=%d negoFlags=%d\n", id, pTarget->negoFlags));
++                              mptscsih_writeSDP1(hd, 0, ii, 0);
++                      }
++              } else {
++                      if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
++                              dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
++                              mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
+                       }
+               }
+       }
++      return;
+ }
+@@ -5094,16 +4977,15 @@ mptscsih_qas_check(MPT_SCSI_HOST *hd, in
+  *    Return: None.
+  */
+ static int
+-mptscsih_doDv(MPT_SCSI_HOST *hd, int bus, int id)
++mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
+ {
+       MPT_ADAPTER             *ioc = hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice              *pTarget;
+       SCSIDevicePage1_t       *pcfg1Data;
+       SCSIDevicePage0_t       *pcfg0Data;
+       u8                      *pbuf1;
+       u8                      *pbuf2;
+-      u8                      *pDvBuf=NULL;
++      u8                      *pDvBuf;
+       dma_addr_t               dvbuf_dma = -1;
+       dma_addr_t               buf1_dma = -1;
+       dma_addr_t               buf2_dma = -1;
+@@ -5127,7 +5009,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
+       char                     firstPass = 1;
+       char                     doFallback = 0;
+       char                     readPage0;
+-      char                     lun;
++      char                     bus, lun;
+       char                     inq0 = 0;
+       if (ioc->spi_data.sdp1length == 0)
+@@ -5141,10 +5023,12 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
+        */
+       if (id == ioc->pfacts[0].PortSCSIID)
+               return 0;
+-ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_IN_PROGRESS;
+       lun = 0;
+-      ddvprintk((MYIOC_s_INFO_FMT "DV Started: bus=%d id=%d dv @ %p\n",ioc->name, bus, id, &dv));
++      bus = (u8) bus_number;
++      ddvtprintk((MYIOC_s_NOTE_FMT
++                      "DV Started: bus=%d id=%d dv @ %p\n",
++                      ioc->name, bus, id, &dv));
+       /* Prep DV structure
+        */
+@@ -5167,8 +5051,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+       iocmd.physDiskNum = -1;
+       iocmd.rsvd = iocmd.rsvd2 = 0;
+-      pMptTarget = ioc->Target_List[bus];
+-      pTarget = pMptTarget->Target[id];
++      pTarget = hd->Targets[id];
+       /* Use tagged commands if possible.
+        */
+@@ -5176,12 +5059,12 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+               if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+                       iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
+               else {
+-                      if (ioc->facts.FWVersion.Word < 0x01000600)
+-                                goto doDv_done;
++                      if (hd->ioc->facts.FWVersion.Word < 0x01000600)
++                              return 0;
+-                      if ((ioc->facts.FWVersion.Word >= 0x01010000) &&
+-                              (ioc->facts.FWVersion.Word < 0x01010B00))
+-                               goto doDv_done;
++                      if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
++                              (hd->ioc->facts.FWVersion.Word < 0x01010B00))
++                              return 0;
+               }
+       }
+@@ -5211,7 +5094,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+       pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
+       if (pDvBuf == NULL)
+-                goto doDv_done;
++              return 0;
+       sz = 0;
+       pbuf1 = (u8 *)pDvBuf;
+@@ -5237,7 +5120,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+       /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
+        */
+       {
+-              SpiCfgData *pspi_data = &ioc->spi_data;
++              SpiCfgData *pspi_data = &hd->ioc->spi_data;
+               if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+                       /* Set the factor from nvram */
+                       nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
+@@ -5247,7 +5130,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+                       if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
+                               (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
+-                              ddvprintk((MYIOC_s_INFO_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
++                              ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
+                                       ioc->name, bus, id, lun));
+                               dv.cmd = MPT_SET_MAX;
+@@ -5260,7 +5143,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+                               cfg.physAddr = cfg1_dma_addr;
+                               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+                               cfg.dir = 1;
+-                              mpt_config(ioc, &cfg);
++                              mpt_config(hd->ioc, &cfg);
+                               goto target_done;
+                       }
+               }
+@@ -5295,7 +5178,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+       /* RAID Volume ID's may double for a physical device. If RAID but
+        * not a physical ID as well, skip DV.
+        */
+-      if ((ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
++      if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
+               goto target_done;
+@@ -5312,10 +5195,8 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF
+       readPage0 = 0;
+       sz = SCSI_MAX_INQUIRY_BYTES;
+       rc = MPT_SCANDV_GOOD;
+-
+-start_DV:
+       while (1) {
+-              ddvprintk((MYIOC_s_INFO_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
++              ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
+               retcode = 0;
+               dv.cmd = MPT_SET_MIN;
+               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+@@ -5324,7 +5205,7 @@ start_DV:
+               cfg.physAddr = cfg1_dma_addr;
+               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+               cfg.dir = 1;
+-              if (mpt_config(ioc, &cfg) != 0)
++              if (mpt_config(hd->ioc, &cfg) != 0)
+                       goto target_done;
+               /* Wide - narrow - wide workaround case
+@@ -5333,9 +5214,9 @@ start_DV:
+                       /* Send an untagged command to reset disk Qs corrupted
+                        * when a parity error occurs on a Request Sense.
+                        */
+-                      if ((ioc->facts.FWVersion.Word >= 0x01000600) ||
+-                              ((ioc->facts.FWVersion.Word >= 0x01010000) &&
+-                              (ioc->facts.FWVersion.Word < 0x01010B00)) ) {
++                      if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
++                              ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
++                              (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
+                               iocmd.cmd = REQUEST_SENSE;
+                               iocmd.data_dma = buf1_dma;
+@@ -5400,6 +5281,12 @@ start_DV:
+                * if PROCESSOR, quit DV.
+                */
+               if (inq0 == TYPE_PROCESSOR) {
++                      mptscsih_initTarget(hd,
++                              bus,
++                              id,
++                              lun,
++                              pbuf1,
++                              sz);
+                       goto target_done;
+               }
+@@ -5426,8 +5313,8 @@ start_DV:
+                               if ((pbuf1[56] & 0x02) == 0) {
+                                       pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+-                                      ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
+-                                      ddvprintk((MYIOC_s_INFO_FMT
++                                      hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
++                                      ddvprintk((MYIOC_s_NOTE_FMT 
+                                           "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", 
+                                           ioc->name, id, pbuf1[56]));
+                               }
+@@ -5440,7 +5327,7 @@ start_DV:
+                       dv.cmd = MPT_SET_MAX;
+               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+-              if (mpt_config(ioc, &cfg) != 0)
++              if (mpt_config(hd->ioc, &cfg) != 0)
+                       goto target_done;
+               if ((!dv.now.width) && (!dv.now.offset))
+@@ -5473,7 +5360,7 @@ start_DV:
+                                       cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+                                       cfg.dir = 0;
+-                                      if (mpt_config(ioc, &cfg) != 0)
++                                      if (mpt_config(hd->ioc, &cfg) != 0)
+                                               goto target_done;
+                                       sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
+@@ -5504,7 +5391,15 @@ start_DV:
+                                               if (!firstPass)
+                                                       doFallback = 1;
+                                       } else {
+-
++                                              ddvprintk((MYIOC_s_NOTE_FMT
++                                                  "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
++                                              hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
++                                              mptscsih_initTarget(hd,
++                                                      bus,
++                                                      id,
++                                                      lun,
++                                                      pbuf1,
++                                                      sz);
+                                               break;  /* test complete */
+                                       }
+                               }
+@@ -5522,7 +5417,7 @@ start_DV:
+                       firstPass = 0;
+               }
+       }
+-      ddvprintk((MYIOC_s_INFO_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
++      ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
+       if (ioc->spi_data.mpt_dv == 0)
+               goto target_done;
+@@ -5534,10 +5429,10 @@ start_DV:
+       if (inq0 != 0)
+               goto target_done;
+-      ddvprintk((MYIOC_s_INFO_FMT "DV: bus, id, lun (%d, %d, %d) PortFlags=%x\n",
++      ddvprintk((MYIOC_s_NOTE_FMT "DV: bus, id, lun (%d, %d, %d) PortFlags=%x\n",
+                       ioc->name, bus, id, lun, ioc->spi_data.PortFlags));
+       if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY ) {
+-              ddvprintk((MYIOC_s_INFO_FMT "DV Basic Only: bus, id, lun (%d, %d, %d) PortFlags=%x\n",
++              ddvprintk((MYIOC_s_NOTE_FMT "DV Basic Only: bus, id, lun (%d, %d, %d) PortFlags=%x\n",
+                       ioc->name, bus, id, lun, ioc->spi_data.PortFlags));
+               goto target_done;
+       }
+@@ -5574,7 +5469,7 @@ start_DV:
+                       u8 skey = hd->pLocal->sense[2] & 0x0F;
+                       u8 asc = hd->pLocal->sense[12];
+                       u8 ascq = hd->pLocal->sense[13];
+-                      ddvprintk((MYIOC_s_WARN_FMT
++                      ddvprintk((MYIOC_s_INFO_FMT
+                               "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
+                               ioc->name, skey, asc, ascq));
+@@ -5646,7 +5541,7 @@ start_DV:
+                                       u8 skey = hd->pLocal->sense[2] & 0x0F;
+                                       u8 asc = hd->pLocal->sense[12];
+                                       u8 ascq = hd->pLocal->sense[13];
+-                                      ddvprintk((MYIOC_s_WARN_FMT
++                                      ddvprintk((MYIOC_s_INFO_FMT
+                                               "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
+                                               ioc->name, skey, asc, ascq));
+                                       if (skey == ILLEGAL_REQUEST) {
+@@ -5665,11 +5560,6 @@ start_DV:
+                                                       ioc->name));
+                                               goto target_done;
+                                       }
+-                               } else if (rc == MPT_SCANDV_FALLBACK) {
+-                                       doFallback = 1; /* set fallback flag */
+-                                       notDone++;
+-                                       goto start_DV;
+-
+                               } else {
+                                       /* All other errors are fatal
+                                        */
+@@ -5812,7 +5702,7 @@ skip_Reserve:
+                                       dv.cmd = MPT_FALLBACK;
+                                       mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+-                                      if (mpt_config(ioc, &cfg) != 0)
++                                      if (mpt_config(hd->ioc, &cfg) != 0)
+                                               goto target_done;
+                                       if ((!dv.now.width) && (!dv.now.offset))
+@@ -5826,7 +5716,7 @@ skip_Reserve:
+                               /* Restart data test if UA, else quit.
+                                */
+                               u8 skey = hd->pLocal->sense[2] & 0x0F;
+-                              ddvprintk((MYIOC_s_WARN_FMT
++                              ddvprintk((MYIOC_s_INFO_FMT
+                                       "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
+                                       hd->pLocal->sense[12], hd->pLocal->sense[13]));
+                               if (skey == UNIT_ATTENTION) {
+@@ -5891,7 +5781,7 @@ skip_Reserve:
+                                               dv.cmd = MPT_FALLBACK;
+                                               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+-                                              if (mpt_config(ioc, &cfg) != 0)
++                                              if (mpt_config(hd->ioc, &cfg) != 0)
+                                                       goto target_done;
+                                               if ((!dv.now.width) && (!dv.now.offset))
+@@ -5909,7 +5799,7 @@ skip_Reserve:
+                               dv.cmd = MPT_FALLBACK;
+                               mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
+-                              if (mpt_config(ioc, &cfg) != 0)
++                              if (mpt_config(hd->ioc, &cfg) != 0)
+                                        goto target_done;
+                               if ((!dv.now.width) && (!dv.now.offset))
+@@ -5922,7 +5812,7 @@ skip_Reserve:
+                               /* Restart data test if UA, else quit.
+                                */
+                               u8 skey = hd->pLocal->sense[2] & 0x0F;
+-                              ddvprintk((MYIOC_s_WARN_FMT
++                              ddvprintk((MYIOC_s_INFO_FMT
+                                       "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
+                                       hd->pLocal->sense[12], hd->pLocal->sense[13]));
+                               if (skey == UNIT_ATTENTION) {
+@@ -5964,8 +5854,8 @@ target_done:
+               /* If disk, not U320, disable QAS
+                */
+               if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
+-                      ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
+-                      ddvprintk((MYIOC_s_INFO_FMT
++                      hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
++                      ddvprintk((MYIOC_s_NOTE_FMT
+                           "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
+               }
+@@ -5980,7 +5870,7 @@ target_done:
+               cfg.physAddr = cfg1_dma_addr;
+               cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+               cfg.dir = 1;
+-              mpt_config(ioc, &cfg);
++              mpt_config(hd->ioc, &cfg);
+                */
+       }
+@@ -5991,18 +5881,13 @@ target_done:
+                       ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
+       }
+-doDv_done:
+       /* Done with the DV scan of the current target
+        */
+       if (pDvBuf)
+               pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
+-      ddvprintk((MYIOC_s_WARN_FMT "DV Done id=%d\n",ioc->name, id));
+-       ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_IN_PROGRESS);
+-       /* Post an IO that was pended while
+-        * DV was running.
+-        */
+-       mptscsih_post_PendingMF_command(ioc);
++      ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
++                      ioc->name, id));
+       return retcode;
+ }
+@@ -6017,8 +5902,6 @@ doDv_done:
+ static void
+ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
+ {
+-      MPT_ADAPTER             *ioc = hd->ioc;
+-      struct _MPT_DEVICE      *pMptTarget;
+       VirtDevice              *pTarget;
+       SCSIDevicePage0_t       *pPage0;
+       SCSIDevicePage1_t       *pPage1;
+@@ -6032,48 +5915,49 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+       switch (cmd) {
+       case MPT_GET_NVRAM_VALS:
+-              ddvprintk((MYIOC_s_INFO_FMT "Getting NVRAM: ",
+-                      ioc->name));
++              ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
++                                                       hd->ioc->name));
+               /* Get the NVRAM values and save in tmax
+                * If not an LVD bus, the adapter minSyncFactor has been
+                * already throttled back.
+                */
+-              negoFlags = ioc->spi_data.noQas;
+-              pMptTarget = ioc->Target_List[0];
+-              pTarget = pMptTarget->Target[id];
+-              if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+-                      data = ioc->spi_data.nvram[id];
+-                      width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+-                      if ((offset = ioc->spi_data.maxSyncOffset) == 0)
+-                              factor = MPT_ASYNC;
+-                      else {
+-                              factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
+-                              if ((factor == 0) || (factor == MPT_ASYNC)){
++              negoFlags = hd->ioc->spi_data.noQas;
++              if ((pTarget = hd->Targets[(int)id]) && !pTarget->raidVolume) {
++                      width = pTarget->maxWidth;
++                      offset = pTarget->maxOffset;
++                      factor = pTarget->minSyncFactor;
++                      negoFlags |= pTarget->negoFlags;
++              } else {
++                      if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
++                              data = hd->ioc->spi_data.nvram[id];
++                              width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
++                              if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
+                                       factor = MPT_ASYNC;
+-                                      offset = 0;
++                              else {
++                                      factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
++                                      if ((factor == 0) || (factor == MPT_ASYNC)){
++                                              factor = MPT_ASYNC;
++                                              offset = 0;
++                                      }
+                               }
+-                      ddvprintk(("NVRAM id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-                              id, width, factor, offset, negoFlags));
++                      } else {
++                              width = MPT_NARROW;
++                              offset = 0;
++                              factor = MPT_ASYNC;
+                       }
+-              } else {
+-                      width = MPT_NARROW;
+-                      offset = 0;
+-                      factor = MPT_ASYNC;
+-                      ddvprintk(("NVRAM_INVALID id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-                              id, width, factor, offset, negoFlags));
+-              }
+-              /* Set the negotiation flags */
+-              if (!width)
+-                      negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
++                      /* Set the negotiation flags */
++                      if (!width)
++                              negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+-              if (!offset)
+-                      negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
++                      if (!offset)
++                              negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
++              }
+               /* limit by adapter capabilities */
+-              width = min(width, ioc->spi_data.maxBusWidth);
+-              offset = min(offset, ioc->spi_data.maxSyncOffset);
+-              factor = max(factor, ioc->spi_data.minSyncFactor);
++              width = min(width, hd->ioc->spi_data.maxBusWidth);
++              offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
++              factor = max(factor, hd->ioc->spi_data.minSyncFactor);
+               /* Check Consistency */
+               if (offset && (factor < MPT_ULTRA2) && !width)
+@@ -6083,13 +5967,13 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+               dv->max.offset = offset;
+               dv->max.factor = factor;
+               dv->max.flags = negoFlags;
+-              ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
++              ddvprintk((" id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+                               id, width, factor, offset, negoFlags));
+               break;
+       case MPT_UPDATE_MAX:
+-              ddvprintk((MYIOC_s_INFO_FMT
+-                      "Updating with SDP0 Data: ", ioc->name));
++              ddvprintk((MYIOC_s_NOTE_FMT
++                      "Updating with SDP0 Data: ", hd->ioc->name));
+               /* Update tmax values with those from Device Page 0.*/
+               pPage0 = (SCSIDevicePage0_t *) pPage;
+               if (pPage0) {
+@@ -6103,10 +5987,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+               dv->now.offset = dv->max.offset;
+               dv->now.factor = dv->max.factor;
+               ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x\n",
+-                      id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
++                              id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
+               break;
+       case MPT_SET_MAX:
++              ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
++                                                              hd->ioc->name));
+               /* Set current to the max values. Update the config page.*/
+               dv->now.width = dv->max.width;
+               dv->now.offset = dv->max.offset;
+@@ -6115,18 +6001,22 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+               pPage1 = (SCSIDevicePage1_t *)pPage;
+               if (pPage1) {
+-                      mpt_setSDP1parameters (dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags,
+-                              &val, &configuration);
++                      mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
++                              dv->now.offset, &val, &configuration, dv->now.flags);
++                      dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
++                              id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
+                       pPage1->RequestedParameters = cpu_to_le32(val);
+                       pPage1->Reserved = 0;
+                       pPage1->Configuration = cpu_to_le32(configuration);
+               }
+-              dnegoprintk(("%s: Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x requested=%08x configuration=%08x\n",
+-                              ioc->name, id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
++              ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
++                              id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
+               break;
+       case MPT_SET_MIN:
++              ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
++                                                              hd->ioc->name));
+               /* Set page to asynchronous and narrow
+                * Do not update now, breaks fallback routine. */
+               width = MPT_NARROW;
+@@ -6136,20 +6026,22 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+               pPage1 = (SCSIDevicePage1_t *)pPage;
+               if (pPage1) {
+-                      mpt_setSDP1parameters (width, factor, offset, negoFlags,
+-                              &val, &configuration);
++                      mptscsih_setDevicePage1Flags (width, factor,
++                              offset, &val, &configuration, negoFlags);
++                      dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
++                              id, width, factor, offset, negoFlags, val, configuration));
+                       pPage1->RequestedParameters = cpu_to_le32(val);
+                       pPage1->Reserved = 0;
+                       pPage1->Configuration = cpu_to_le32(configuration);
+               }
+-              dnegoprintk(("%s: Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x requested=%08x configuration=%08x\n",
+-                              ioc->name, id, width, factor, offset, negoFlags, val, configuration));
++              ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
++                              id, width, factor, offset, val, configuration, negoFlags));
+               break;
+       case MPT_FALLBACK:
+-              ddvprintk((MYIOC_s_INFO_FMT
++              ddvprintk((MYIOC_s_NOTE_FMT
+                       "Fallback: Start: offset %d, factor %x, width %d \n",
+-                              ioc->name, dv->now.offset,
++                              hd->ioc->name, dv->now.offset,
+                               dv->now.factor, dv->now.width));
+               width = dv->now.width;
+               offset = dv->now.offset;
+@@ -6212,32 +6104,31 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+               pPage1 = (SCSIDevicePage1_t *)pPage;
+               if (pPage1) {
+-                      mpt_setSDP1parameters (width, factor, offset, dv->now.flags,
+-                              &val, &configuration);
++                      mptscsih_setDevicePage1Flags (width, factor, offset, &val,
++                                              &configuration, dv->now.flags);
++                      dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
++                           id, width, offset, factor, dv->now.flags, val, configuration));
+                       pPage1->RequestedParameters = cpu_to_le32(val);
+                       pPage1->Reserved = 0;
+                       pPage1->Configuration = cpu_to_le32(configuration);
+               }
+-              ddvprintk(("%s: Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x requested=%08x configuration=%08x\n",
+-                           ioc->name, id, width, offset, factor, dv->now.flags, val, configuration));
++              ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
++                           id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
+               break;
+       case MPT_SAVE:
+-              ddvprintk((MYIOC_s_INFO_FMT
+-                      "Saving to pTarget: "
+-                      "id=%d width=%x factor=%x offset=%d negoFlags=%x\n",
+-                              ioc->name, id, dv->now.width, dv->now.factor,
+-                              dv->now.offset, dv->now.flags));
++              ddvprintk((MYIOC_s_NOTE_FMT
++                      "Saving to Target structure: ", hd->ioc->name));
++              ddvprintk(("id=%d width=%x factor=%x offset=%d negoFlags=%x\n",
++                           id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
+               /* Save these values to target structures
+                * or overwrite nvram (phys disks only).
+                */
+-              pMptTarget = ioc->Target_List[0];
+-              pTarget = pMptTarget->Target[id];
+-              if (pTarget && !pTarget->raidVolume ) {
++              if ((pTarget = hd->Targets[(int)id]) && !pTarget->raidVolume ) {
+                       pTarget->maxWidth = dv->now.width;
+                       pTarget->maxOffset = dv->now.offset;
+                       pTarget->minSyncFactor = dv->now.factor;
+@@ -6246,8 +6137,8 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+                       /* Preserv all flags, use
+                        * read-modify-write algorithm
+                        */
+-                      if (ioc->spi_data.nvram) {
+-                              data = ioc->spi_data.nvram[id];
++                      if (hd->ioc->spi_data.nvram) {
++                              data = hd->ioc->spi_data.nvram[id];
+                               if (dv->now.width)
+                                       data &= ~MPT_NVRAM_WIDE_DISABLE;
+@@ -6260,14 +6151,13 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
+                               data &= ~MPT_NVRAM_SYNC_MASK;
+                               data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
+-                              ioc->spi_data.nvram[id] = data;
++                              hd->ioc->spi_data.nvram[id] = data;
+                       }
+               }
+               break;
+       }
+ }
+-
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ /*    mptscsih_fillbuf - fill a buffer with a special data pattern
+  *            cleanup. For bus scan only.
+@@ -6422,11 +6312,10 @@ EXPORT_SYMBOL(mptscsih_taskmgmt_complete
+ EXPORT_SYMBOL(mptscsih_scandv_complete);
+ EXPORT_SYMBOL(mptscsih_event_process);
+ EXPORT_SYMBOL(mptscsih_ioc_reset);
+-EXPORT_SYMBOL(mptscsih_InternalCmdTimer_expired);
++EXPORT_SYMBOL(mptscsih_timer_expired);
+ EXPORT_SYMBOL(mptscsih_readFCDevicePage0);
+ EXPORT_SYMBOL(mptscsih_change_queue_depth);
+ EXPORT_SYMBOL(mptscsih_TMHandler);
+-EXPORT_SYMBOL(mptscsih_TM_timeout);
+ EXPORT_SYMBOL(mptscsih_sanity_check);
+ EXPORT_SYMBOL(mptscsih_poll);
+ EXPORT_SYMBOL(mptscsih_do_cmd);
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptscsih.h linux-2.6.9-55.0.12/drivers/message/fusion/mptscsih.h
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptscsih.h       2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptscsih.h      2007-11-02 09:10:23.000000000 +0100
+@@ -5,8 +5,8 @@
+  *          LSIFC9xx/LSI409xx Fibre Channel
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  *  $Id: mptscsih.h,v 1.1.2.2 2003/05/07 14:08:35 Exp $
+  */
+@@ -54,17 +54,7 @@
+  *    SCSI Public stuff...
+  */
+-#define MPT_SCANDV_GOOD                       (0x00000000) /* must be 0 */
+-#define MPT_SCANDV_DID_RESET          (0x00000001)
+-#define MPT_SCANDV_SENSE              (0x00000002)
+-#define MPT_SCANDV_SOME_ERROR         (0x00000004)
+-#define MPT_SCANDV_SELECTION_TIMEOUT  (0x00000008)
+-#define MPT_SCANDV_ISSUE_SENSE                (0x00000010)
+-#define MPT_SCANDV_FALLBACK           (0x00000020)
+-#define MPT_SCANDV_BUSY                       (0x00000040)
+-
+-//#define MPT_SCSI_CMD_PER_DEV_HIGH   64
+-#define MPT_SCSI_CMD_PER_DEV_HIGH      48
++#define MPT_SCSI_CMD_PER_DEV_HIGH     64
+ #define MPT_SCSI_CMD_PER_DEV_LOW      32
+ #define MPT_SCSI_CMD_PER_LUN          7
+@@ -133,7 +123,7 @@ extern int mptscsih_taskmgmt_complete(MP
+ extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+ extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+-extern void mptscsih_InternalCmdTimer_expired(unsigned long data);
++extern void mptscsih_timer_expired(unsigned long data);
+ extern int mptscsih_readFCDevicePage0(MPT_ADAPTER *ioc, u8 bus, u8 targetId, pFCDevicePage0_t fcDevicePage);
+ extern void mptscsih_hot_plug_worker_thread(void * arg);
+ extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+@@ -141,4 +131,4 @@ extern int mptscsih_change_queue_depth(s
+ extern int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
+ extern int mptscsih_sanity_check(struct scsi_device *sdev);
+ extern void mptscsih_poll(struct scsi_device *sdev);
+-extern void scsi_print_command(struct scsi_cmnd *cmd);
++extern void scsi_print_command(struct scsi_cmnd *cmd);
+\ Pas de fin de ligne à la fin du fichier.
+diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptspi.c linux-2.6.9-55.0.12/drivers/message/fusion/mptspi.c
+--- linux-2.6.9-67.0.1/drivers/message/fusion/mptspi.c 2007-12-21 11:40:54.000000000 +0100
++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptspi.c        2007-11-02 09:10:23.000000000 +0100
+@@ -3,8 +3,8 @@
+  *      For use with LSI Logic PCI chip/adapter(s)
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+- *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:mpt_linux_developer@lsi.com)
++ *  Copyright (c) 1999-2005 LSI Logic Corporation
++ *  (mailto:mpt_linux_developer@lsil.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -73,7 +73,6 @@
+ MODULE_AUTHOR(MODULEAUTHOR);
+ MODULE_DESCRIPTION(my_NAME);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(my_VERSION);
+ /* Command line args */
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+@@ -146,13 +145,12 @@ static struct scsi_host_template mptspi_
+       .change_queue_depth             = mptscsih_change_queue_depth,
+ #endif
+       .eh_abort_handler               = mptscsih_abort,
+-        .eh_device_reset_handler        = mptscsih_dev_reset,
+       .eh_bus_reset_handler           = mptscsih_bus_reset,
+       .eh_host_reset_handler          = mptscsih_host_reset,
+       .bios_param                     = mptscsih_bios_param,
+       .can_queue                      = MPT_SCSI_CAN_QUEUE,
+       .this_id                        = -1,
+-      .sg_tablesize                   = CONFIG_FUSION_MAX_SGE,
++      .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
+       .max_sectors                    = 8192,
+       .cmd_per_lun                    = 7,
+       .use_clustering                 = ENABLE_CLUSTERING,
+@@ -191,6 +189,8 @@ mptspi_probe(struct pci_dev *pdev, const
+       MPT_ADAPTER             *ioc;
+       unsigned long            flags;
+       int                      sz, ii;
++      int                      numSGE = 0;
++      int                      scale;
+       int                      ioc_cap;
+       u8                      *mem;
+       int                     error=0;
+@@ -269,7 +269,7 @@ mptspi_probe(struct pci_dev *pdev, const
+               ioc->name, mpt_can_queue, ioc->req_depth,
+               sh->can_queue));
+-      sh->max_id = ioc->DevicesPerBus;
++      sh->max_id = MPT_MAX_SCSI_DEVICES;
+       sh->max_lun = MPT_LAST_LUN + 1;
+       sh->max_channel = 0;
+@@ -278,7 +278,36 @@ mptspi_probe(struct pci_dev *pdev, const
+       /* Required entry.
+        */
+       sh->unique_id = ioc->id;
+-      sh->sg_tablesize = ioc->sg_tablesize;
++
++      /* Verify that we won't exceed the maximum
++       * number of chain buffers
++       * We can optimize:  ZZ = req_sz/sizeof(SGE)
++       * For 32bit SGE's:
++       *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
++       *               + (req_sz - 64)/sizeof(SGE)
++       * A slightly different algorithm is required for
++       * 64bit SGEs.
++       */
++      scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
++      if (sizeof(dma_addr_t) == sizeof(u64)) {
++              numSGE = (scale - 1) *
++                (ioc->facts.MaxChainDepth-1) + scale +
++                (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
++                sizeof(u32));
++      } else {
++              numSGE = 1 + (scale - 1) *
++                (ioc->facts.MaxChainDepth-1) + scale +
++                (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
++                sizeof(u32));
++      }
++
++      if (numSGE < sh->sg_tablesize) {
++              /* Reset this value */
++              dprintk((MYIOC_s_INFO_FMT
++                "Resetting sg_tablesize to %d from %d\n",
++                ioc->name, numSGE, sh->sg_tablesize));
++              sh->sg_tablesize = numSGE;
++      }
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13))
+       /* Set the pci device pointer in Scsi_Host structure.
+@@ -307,29 +336,29 @@ mptspi_probe(struct pci_dev *pdev, const
+       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+                ioc->name, hd->ScsiLookup, sz));
+-      for (ii=0; ii < ioc->NumberOfBuses; ii++) {
+-              /* Allocate memory for the device structures.
+-               * A non-Null pointer at an offset
+-               * indicates a device exists.
+-               */
+-              sz = ioc->DevicesPerBus * sizeof(void *);
+-              mem = kmalloc(sz, GFP_ATOMIC);
+-              if (mem == NULL) {
+-                      error = -ENOMEM;
+-                      goto out_mptspi_probe;
+-              }
++      /* Allocate memory for the device structures.
++       * A non-Null pointer at an offset
++       * indicates a device exists.
++       * max_id = 1 + maximum id (hosts.h)
++       */
++      sz = sh->max_id * sizeof(void *);
++      mem = kmalloc(sz, GFP_ATOMIC);
++      if (mem == NULL) {
++              error = -ENOMEM;
++              goto out_mptspi_probe;
++      }
+-              memset(mem, 0, sz);
+-              ioc->Target_List[ii] = (struct _MPT_DEVICE *) mem;
++      memset(mem, 0, sz);
++      hd->Targets = (VirtDevice **) mem;
+-              dinitprintk((KERN_INFO
+-                " For Bus=%d, Target_List=%p sz=%d\n", ii, mem, sz));
+-      }
++      dprintk((KERN_INFO
++        "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+       /* Clear the TM flags
+        */
+       hd->tmPending = 0;
+       hd->tmState = TM_STATE_NONE;
++      hd->resetPending = 0;
+       hd->abortSCpnt = NULL;
+       /* Clear the pointer used to store
+@@ -339,21 +368,16 @@ mptspi_probe(struct pci_dev *pdev, const
+        */
+       hd->cmdPtr = NULL;
+-      /* Initialize this IOC's  timers
++      /* Initialize this SCSI Hosts' timers
+        * To use, set the timer expires field
+-       * and add_timer.Used for internally
+-         * generated commands.
++       * and add_timer
+        */
+-       init_timer(&hd->InternalCmdTimer);
+-       hd->InternalCmdTimer.data = (unsigned long) hd;
+-       hd->InternalCmdTimer.function = mptscsih_InternalCmdTimer_expired;
+-
+-       init_timer(&ioc->TMtimer);
+-       ioc->TMtimer.data = (unsigned long) ioc;
+-       ioc->TMtimer.function = mptscsih_TM_timeout;
++      init_timer(&hd->timer);
++      hd->timer.data = (unsigned long) hd;
++      hd->timer.function = mptscsih_timer_expired;
+-       ioc->spi_data.Saf_Te = mpt_saf_te;
+-       hd->mpt_pq_filter = mpt_pq_filter;
++      ioc->spi_data.Saf_Te = mpt_saf_te;
++      hd->mpt_pq_filter = mpt_pq_filter;
+ #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+       if (ioc->spi_data.maxBusWidth > mpt_width)
+@@ -364,6 +388,7 @@ mptspi_probe(struct pci_dev *pdev, const
+               ioc->spi_data.maxSyncOffset = 0;
+       }
+       ioc->spi_data.mpt_dv = mpt_dv;
++      hd->negoNvram = 0;
+       ddvprintk((MYIOC_s_INFO_FMT
+               "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n",
+@@ -374,7 +399,7 @@ mptspi_probe(struct pci_dev *pdev, const
+               mpt_saf_te,
+               mpt_pq_filter));
+ #else
+-
++      hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
+       ddvprintk((MYIOC_s_INFO_FMT
+               "saf_te %x mpt_pq_filter %x\n",
+               ioc->name,
+@@ -387,18 +412,18 @@ mptspi_probe(struct pci_dev *pdev, const
+               ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
+       else
+               ioc->spi_data.noQas = 0;
+-/* enable domain validation flags */
+       for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+-ioc->spi_data.dvStatus[ii] =
++              ioc->spi_data.dvStatus[ii] =
++                MPT_SCSICFG_NEGOTIATE;
+-(MPT_SCSICFG_NEGOTIATE | MPT_SCSICFG_DV_NOT_DONE);
++      for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
++              ioc->spi_data.dvStatus[ii] |=
++                MPT_SCSICFG_DV_NOT_DONE;
+       init_waitqueue_head(&hd->scandv_waitq);
+       hd->scandv_wait_done = 0;
+       hd->last_queue_full = 0;
+-        init_waitqueue_head(&hd->TM_waitq);
+-        hd->TM_wait_done = 0;
+       error = scsi_add_host (sh, &ioc->pcidev->dev);
+       if(error) {
+@@ -414,10 +439,6 @@ ioc->spi_data.dvStatus[ii] =
+                   0, 0, 0, 0, 5 /* 5 second timeout */);
+       }
+-       dnegoprintk((MYIOC_s_WARN_FMT "%s: writeSDP1: ALL_IDS\n",
+-               ioc->name, __FUNCTION__));
+-       mpt_writeSDP1(ioc, 0, 0, MPT_SCSICFG_ALL_IDS);
+-
+       scsi_scan_host(sh);
+       return 0;
+@@ -464,7 +485,7 @@ mptspi_init(void)
+       if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) {
+               devtprintk((KERN_INFO MYNAM
+-        ": Registered for IOC event notifications mptspiDoneCtx=%08x\n", mptspiDoneCtx));
++                ": Registered for IOC event notifications\n"));
+       }
+       if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) {
index 7322735..d058295 100644 (file)
@@ -31,3 +31,4 @@ quota-deadlock-on-pagelock-ext3.patch
 export-nr_free_buffer_pages.patch
 vfs-keep-inode-hashed-for-clear-inode.patch
 modpost_external_module_updates_rhel4.patch
+mpt-fusion-downgrade-to-3_02_73-rhel4.patch