--- /dev/null
+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) {