static int     SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
 static int     SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
 static int     mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
-static int     mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag);
+static 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);
 static int     SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
 static int     GetLanConfigPages(MPT_ADAPTER *ioc);
 static int     GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
 static int     GetIoUnitPage2(MPT_ADAPTER *ioc);
+int            mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 static int     mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
 static int     mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
 static void    mpt_read_ioc_pg_1(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);
+static int     mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
+static int     mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
 
 #ifdef CONFIG_PROC_FS
 static int     procmpt_summary_read(char *buf, char **start, off_t offset,
                        pCfg->wait_done = 1;
                        wake_up(&mpt_waitq);
                }
+       } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
+               /* we should be always getting a reply frame */
+               memcpy(ioc->persist_reply_frame, reply,
+                   min(MPT_DEFAULT_FRAME_SIZE,
+                   4*reply->u.reply.MsgLength));
+               del_timer(&ioc->persist_timer);
+               ioc->persist_wait_done = 1;
+               wake_up(&mpt_waitq);
        } else {
                printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
                                ioc->name, func);
                mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
                                u.frame.linkage.list);
                list_del(&mf->u.frame.linkage.list);
+               mf->u.frame.linkage.arg1 = 0;
                mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;  /* byte */
                req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
                                                                /* u16! */
 
        /*  Put Request back on FreeQ!  */
        spin_lock_irqsave(&ioc->FreeQlock, flags);
+       mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
        list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
 #ifdef MFCNT
        ioc->mfcnt--;
 
        /* Make sure there are no doorbells */
        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-       
+
        return r;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_host_page_access_control - provides mechanism for the host
+ * driver to control the IOC's Host Page Buffer access.
+ * @ioc: Pointer to MPT adapter structure
+ * @access_control_value: define bits below
+ *
+ * Access Control Value - bits[15:12]
+ * 0h Reserved
+ * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
+ * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
+ * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+
+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)
+           & MPI_DOORBELL_ACTIVE)
+           return -1;
+
+       CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
+       CHIPREG_WRITE32(&ioc->chip->Doorbell,
+               ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
+                <<MPI_DOORBELL_FUNCTION_SHIFT) |
+                (access_control_value<<12)));
+
+       /* Wait for IOC to clear Doorbell Status bit */
+       if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+               return -2;
+       }else
+               return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *     mpt_host_page_alloc - allocate system memory for the fw
+ *     If we already allocated memory in past, then resend the same pointer.
+ *     ioc@: Pointer to pointer to IOC adapter
+ *     ioc_init@: Pointer to ioc init config page
+ *
+ *     Returns 0 for success, non-zero for failure.
+ */
+static int
+mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
+{
+       char    *psge;
+       int     flags_length;
+       u32     host_page_buffer_sz=0;
+
+       if(!ioc->HostPageBuffer) {
+
+               host_page_buffer_sz =
+                   le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
+
+               if(!host_page_buffer_sz)
+                       return 0; /* fw doesn't need any host buffers */
+
+               /* spin till we get enough memory */
+               while(host_page_buffer_sz > 0) {
+
+                       if((ioc->HostPageBuffer = pci_alloc_consistent(
+                           ioc->pcidev,
+                           host_page_buffer_sz,
+                           &ioc->HostPageBuffer_dma)) != NULL) {
+
+                               dinitprintk((MYIOC_s_INFO_FMT
+                                   "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
+                                   ioc->name,
+                                   ioc->HostPageBuffer,
+                                   ioc->HostPageBuffer_dma,
+                                   hst_page_buffer_sz));
+                               ioc->alloc_total += host_page_buffer_sz;
+                               ioc->HostPageBuffer_sz = host_page_buffer_sz;
+                               break;
+                       }
+
+                       host_page_buffer_sz -= (4*1024);
+               }
+       }
+
+       if(!ioc->HostPageBuffer) {
+               printk(MYIOC_s_ERR_FMT
+                   "Failed to alloc memory for host_page_buffer!\n",
+                   ioc->name);
+               return -999;
+       }
+
+       psge = (char *)&ioc_init->HostPageBufferSGE;
+       flags_length = 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)) {
+           flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
+       }
+       flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
+       flags_length |= ioc->HostPageBuffer_sz;
+       mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
+       ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
+
+return 0;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mpt_verify_adapter - Given a unique IOC identifier, set pointer to
                ioc->prod_name = "LSI53C1035";
                ioc->bus_type = SCSI;
        }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
+               ioc->prod_name = "LSISAS1064";
+               ioc->bus_type = SAS;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
+               ioc->prod_name = "LSISAS1066";
+               ioc->bus_type = SAS;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
+               ioc->prod_name = "LSISAS1068";
+               ioc->bus_type = SAS;
+               ioc->errata_flag_1064 = 1;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
+               ioc->prod_name = "LSISAS1064E";
+               ioc->bus_type = SAS;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
+               ioc->prod_name = "LSISAS1066E";
+               ioc->bus_type = SAS;
+       }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
+               ioc->prod_name = "LSISAS1068E";
+               ioc->bus_type = SAS;
+       }
 
        if (ioc->errata_flag_1064)
                pci_disable_io_access(pdev);
         *      and we try GetLanConfigPages again...
         */
        if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
-               if (ioc->bus_type == FC) {
+               if (ioc->bus_type == SAS) {
+
+                       /* 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)
+                                       return -1;
+                       }
+
+                       /* Find IM volumes
+                        */
+                       mpt_findImVolumes(ioc);
+
+               } else if (ioc->bus_type == FC) {
                        /*
                         *  Pre-fetch FC port WWN and stuff...
                         *  (FCPortPage0_t stuff)
 
        if (ioc->cached_fw != NULL) {
                ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
-               if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) {
+               if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
                        printk(KERN_WARNING MYNAM
                                ": firmware downloadboot failure (%d)!\n", ret);
                }
 
        kfree(ioc->ChainToChain);
        ioc->ChainToChain = NULL;
+
+       if (ioc->HostPageBuffer != NULL) {
+               if((ret = mpt_host_page_access_control(ioc,
+                   MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
+                       printk(KERN_ERR MYNAM
+                          ": %s: host page buffers free failed (%d)!\n",
+                           __FUNCTION__, ret);
+               }
+               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,
+                               ioc->HostPageBuffer_dma);
+               ioc->HostPageBuffer = NULL;
+               ioc->HostPageBuffer_sz = 0;
+               ioc->alloc_total -= ioc->HostPageBuffer_sz;
+       }
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
         *  Loop here waiting for IOC to come READY.
         */
        ii = 0;
-       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15;    /* 15 seconds */
+       cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5;     /* 5 seconds */
 
        while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
                if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
                                le32_to_cpu(facts->CurrentSenseBufferHighAddr);
                facts->CurReplyFrameSize =
                                le16_to_cpu(facts->CurReplyFrameSize);
+               facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
 
                /*
                 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
        ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
                   ioc->name, ioc->upload_fw, ioc->facts.Flags));
 
-       if (ioc->bus_type == FC)
+       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 "facts.MsgVersion=%x\n",
+                  ioc->name, ioc->facts.MsgVersion));
+       if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
+               // set MsgVersion and HeaderVersion host driver was built with
+               ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
+               ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
+
+               if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
+                       ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
+               } else if(mpt_host_page_alloc(ioc, &ioc_init))
+                       return -99;
+       }
        ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);   /* in BYTES */
 
        if (sizeof(dma_addr_t) == sizeof(u64)) {
                ioc_init.HostMfaHighAddr = cpu_to_le32(0);
                ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
        }
-               
+
        ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
        ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
+       ioc->facts.MaxDevices = ioc_init.MaxDevices;
+       ioc->facts.MaxBuses = ioc_init.MaxBuses;
 
        dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
                        ioc->name, &ioc_init));
 
        r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
                                sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
-       if (r != 0)
+       if (r != 0) {
+               printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
                return r;
+       }
 
        /* No need to byte swap the multibyte fields in the reply
         * since we don't even look at it's contents.
 {
        PortEnable_t             port_enable;
        MPIDefaultReply_t        reply_buf;
-       int      ii;
+       int      rc;
        int      req_sz;
        int      reply_sz;
 
 
        /* RAID FW may take a long time to enable
         */
-       if (ioc->bus_type == FC) {
-               ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
-                               reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
-       } else {
-               ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
+       if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+                       > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) {
+               rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
                                reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
+       } else {
+               rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
+                               reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag);
        }
-
-       if (ii != 0)
-               return ii;
-
-       /* We do not even look at the reply, so we need not
-        * swap the multi-byte fields.
-        */
-
-       return 0;
+       return rc;
 }
 
 /*
  *             <0 for fw upload failure.
  */
 static int
-mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
+mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
 {
-       MpiFwHeader_t           *pFwHeader;
        MpiExtImageHeader_t     *pExtImage;
        u32                      fwSize;
        u32                      diag0val;
        u32                      load_addr;
        u32                      ioc_state=0;
 
-       ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n",
-                               ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
-
-       if ( ioc->facts.FWImageSize == 0 )
-               return -1;
-
-       if (ioc->cached_fw == NULL)
-               return -2;
-
-       /* prevent a second downloadboot and memory free with alt_ioc */
-       if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
-               ioc->alt_ioc->cached_fw = NULL;
+       ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
+                               ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
 
        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
                                ioc->name, count));
                        break;
                }
-               /* wait 1 sec */
+               /* wait .1 sec */
                if (sleepFlag == CAN_SLEEP) {
-                       msleep_interruptible (1000);
+                       msleep_interruptible (100);
                } else {
-                       mdelay (1000);
+                       mdelay (100);
                }
        }
 
        if ( count == 30 ) {
-               ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER 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;
        }
        /* Set the DiagRwEn and Disable ARM bits */
        CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
 
-       pFwHeader = (MpiFwHeader_t *) ioc->cached_fw;
        fwSize = (pFwHeader->ImageSize + 3)/4;
        ptrFw = (u32 *) pFwHeader;
 
        /* Clear the internal flash bad bit - autoincrementing register,
         * so must do two writes.
         */
-       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
-       diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
-       diagRwData |= 0x4000000;
-       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
-       CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+       if (ioc->bus_type == SCSI) {
+               /*
+                * 1030 and 1035 H/W errata, workaround to access
+                * the ClearFlashBadSignatureBit
+                */
+               CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+               diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
+               diagRwData |= 0x40000000;
+               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 {
+                       mdelay (1);
+               }
+       }
 
        if (ioc->errata_flag_1064)
                pci_disable_io_access(ioc->pcidev);
 
        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-       ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\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);
+       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);
        /* Write 0xFF to reset the sequencer */
        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 
+       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;
+               }
+       }
+
        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_INFO_FMT "downloadboot: SendIocInit failed\n",
                                        ioc->name));
 
                                /* wait 1 sec */
                                if (sleepFlag == CAN_SLEEP) {
-                                       ssleep(1);
+                                       msleep_interruptible (1000);
                                } else {
                                        mdelay (1000);
                                }
                        }
-                       if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
+                       if ((count = mpt_downloadboot(ioc,
+                               (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
                                printk(KERN_WARNING MYNAM
                                        ": firmware downloadboot failure (%d)!\n", count);
                        }
        return rc;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *     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;
+               break;
+       }
+
+       printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
+
+       /* Get a MF for this command.
+        */
+       if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
+               printk("%s: no msg frames!\n",__FUNCTION__);
+               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 = persist_opcode;
+
+       init_timer(&ioc->persist_timer);
+       ioc->persist_timer.data = (unsigned long) ioc;
+       ioc->persist_timer.function = mpt_timer_expired;
+       ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
+       ioc->persist_wait_done=0;
+       add_timer(&ioc->persist_timer);
+       mpt_put_msg_frame(mpt_base_index, ioc, mf);
+       wait_event(mpt_waitq, ioc->persist_wait_done);
+
+       sasIoUnitCntrReply =
+           (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
+       if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
+               printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
+                   __FUNCTION__,
+                   sasIoUnitCntrReply->IOCStatus,
+                   sasIoUnitCntrReply->IOCLogInfo);
+               return -1;
+       }
+
+       printk("%s: success\n",__FUNCTION__);
+       return 0;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     GetIoUnitPage2 - Retrieve BIOS version and boot order information.
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static char *
-EventDescriptionStr(u8 event, u32 evData0)
+static void
+EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 {
        char *ds;
 
                        ds = "Events(OFF) Change";
                break;
        case MPI_EVENT_INTEGRATED_RAID:
-               ds = "Integrated Raid";
+       {
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_RAID_RC_VOLUME_CREATED :
+                       ds = "Integrated Raid: Volume Created";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_DELETED :
+                       ds = "Integrated Raid: Volume Deleted";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
+                       ds = "Integrated Raid: Volume Settings Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
+                       ds = "Integrated Raid: Volume Status Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
+                       ds = "Integrated Raid: Volume Physdisk Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
+                       ds = "Integrated Raid: Physdisk Created";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
+                       ds = "Integrated Raid: Physdisk Deleted";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
+                       ds = "Integrated Raid: Physdisk Settings Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
+                       ds = "Integrated Raid: Physdisk Status Changed";
+                       break;
+               case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
+                       ds = "Integrated Raid: Domain Validation Needed";
+                       break;
+               case MPI_EVENT_RAID_RC_SMART_DATA :
+                       ds = "Integrated Raid; Smart Data";
+                       break;
+               case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
+                       ds = "Integrated Raid: Replace Action Started";
+                       break;
+               default:
+                       ds = "Integrated Raid";
                break;
+               }
+               break;
+       }
+       case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
+               ds = "SCSI Device Status Change";
+               break;
+       case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+       {
+               u8 ReasonCode = (u8)(evData0 >> 16);
+               switch (ReasonCode) {
+               case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
+                       ds = "SAS Device Status Change: Added";
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+                       ds = "SAS Device Status Change: Deleted";
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+                       ds = "SAS Device Status Change: SMART Data";
+                       break;
+               case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+                       ds = "SAS Device Status Change: No Persistancy Added";
+                       break;
+               default:
+                       ds = "SAS Device Status Change: Unknown";
+               break;
+               }
+               break;
+       }
+       case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
+               ds = "Bus Timer Expired";
+               break;
+       case MPI_EVENT_QUEUE_FULL:
+               ds = "Queue Full";
+               break;
+       case MPI_EVENT_SAS_SES:
+               ds = "SAS SES Event";
+               break;
+       case MPI_EVENT_PERSISTENT_TABLE_FULL:
+               ds = "Persistent Table Full";
+               break;
+       case MPI_EVENT_SAS_PHY_LINK_STATUS:
+               ds = "SAS PHY Link Status";
+               break;
+       case MPI_EVENT_SAS_DISCOVERY_ERROR:
+               ds = "SAS Discovery Error";
+               break;
+
        /*
         *  MPT base "custom" events may be added here...
         */
                ds = "Unknown";
                break;
        }
-       return ds;
+       strcpy(evStr,ds);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
        int ii;
        int r = 0;
        int handlers = 0;
-       char *evStr;
+       char evStr[100];
        u8 event;
 
        /*
                evData0 = le32_to_cpu(pEventReply->Data[0]);
        }
 
-       evStr = EventDescriptionStr(event, evData0);
+       EventDescriptionStr(event, evData0, evStr);
        devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
                        ioc->name,
                        evStr,
         *  Do general / base driver event processing
         */
        switch(event) {
-       case MPI_EVENT_NONE:                    /* 00 */
-       case MPI_EVENT_LOG_DATA:                /* 01 */
-       case MPI_EVENT_STATE_CHANGE:            /* 02 */
-       case MPI_EVENT_UNIT_ATTENTION:          /* 03 */
-       case MPI_EVENT_IOC_BUS_RESET:           /* 04 */
-       case MPI_EVENT_EXT_BUS_RESET:           /* 05 */
-       case MPI_EVENT_RESCAN:                  /* 06 */
-       case MPI_EVENT_LINK_STATUS_CHANGE:      /* 07 */
-       case MPI_EVENT_LOOP_STATE_CHANGE:       /* 08 */
-       case MPI_EVENT_LOGOUT:                  /* 09 */
-       case MPI_EVENT_INTEGRATED_RAID:         /* 0B */
-       case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:       /* 0C */
-       default:
-               break;
        case MPI_EVENT_EVENT_CHANGE:            /* 0A */
                if (evDataLen) {
                        u8 evState = evData0 & 0xFF;
                        }
                }
                break;
+       default:
+               break;
        }
 
        /*
 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);
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/