/*******************************************************************************
*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved. 
*
*Redistribution and use in source and binary forms, with or without modification, are permitted provided 
*that the following conditions are met: 
*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
*following disclaimer. 
*2. Redistributions in binary form must reproduce the above copyright notice, 
*this list of conditions and the following disclaimer in the documentation and/or other materials provided
*with the distribution. 
*
*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED 
*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
*BUSINESS INTERRUPTION) 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 OF THIS 
*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE

********************************************************************************/
/*******************************************************************************/
/** \file
 *
 *
 * This file contains Management IOCTL APIs
 *
 */
#include <sys/cdefs.h>
#include <dev/pms/config.h>

#include <dev/pms/freebsd/driver/common/osenv.h>
#include <dev/pms/freebsd/driver/common/ostypes.h>
#include <dev/pms/freebsd/driver/common/osdebug.h>

#include <dev/pms/RefTisa/sallsdk/api/sa.h>
#include <dev/pms/RefTisa/sallsdk/api/saapi.h>
#include <dev/pms/RefTisa/sallsdk/api/saosapi.h>

#include <dev/pms/RefTisa/tisa/api/titypes.h>
#include <dev/pms/RefTisa/tisa/api/ostiapi.h>
#include <dev/pms/RefTisa/tisa/api/tiapi.h>
#include <dev/pms/RefTisa/tisa/api/tiglobal.h>

#ifdef FDS_SM
#include <dev/pms/RefTisa/sat/api/sm.h>
#include <dev/pms/RefTisa/sat/api/smapi.h>
#include <dev/pms/RefTisa/sat/api/tdsmapi.h>
#endif

#ifdef FDS_DM
#include <dev/pms/RefTisa/discovery/api/dm.h>
#include <dev/pms/RefTisa/discovery/api/dmapi.h>
#include <dev/pms/RefTisa/discovery/api/tddmapi.h>
#endif

#include <dev/pms/RefTisa/tisa/sassata/sas/common/tdtypes.h>
#include <dev/pms/freebsd/driver/common/osstring.h>
#include <dev/pms/RefTisa/tisa/sassata/common/tdutil.h>
#include <dev/pms/RefTisa/sallsdk/spc/mpidebug.h>

#ifdef INITIATOR_DRIVER
#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdtypes.h>
#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itddefs.h>
#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdglobl.h>
#endif

#ifdef TARGET_DRIVER
#include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdglobl.h>
#include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdxchg.h>
#include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdtypes.h>
#endif

#include <dev/pms/RefTisa/tisa/sassata/common/tdsatypes.h>
#include <dev/pms/RefTisa/tisa/sassata/common/tdproto.h>
#include <dev/pms/RefTisa/tisa/sassata/common/tdioctl.h>

#include <dev/pms/RefTisa/sallsdk/spc/sadefs.h>
#include <dev/pms/RefTisa/sallsdk/spc/spcdefs.h>
#include <dev/pms/RefTisa/sallsdk/spc/mpi.h>
#include <dev/pms/RefTisa/sallsdk/spc/sallist.h>
#include <dev/pms/RefTisa/sallsdk/spc/satypes.h>


#define agFieldOffset(baseType,fieldName) \
            /*lint -e545 */ \
            ((bit32)((bitptr)(&(((baseType *)0)->fieldName)))) \

#ifdef SA_LL_API_TEST
osGLOBAL bit32 tdLlApiTestIoctl(tiRoot_t *tiRoot,
                                tiIOCTLPayload_t *agIOCTLPayload,
                                void *agParam1,
                                void *agParam2,
                                void *agParam3);
#endif /* SA_LL_API_TEST */


extern bit32 volatile sgpioResponseSet;

#ifdef SPC_ENABLE_PROFILE
/*****************************************************************************
*
* tdipFWProfileIoctl
*
* Purpose:  This routine is called to process the FW Profile IOCTL function.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32 tdipFWProfileIoctl(
                        tiRoot_t            *tiRoot,
                        tiIOCTLPayload_t    *agIOCTLPayload,
                        void                *agParam1,
                        void                *agParam2,
                        void                *agParam3
                        )
{

  bit32                status = IOCTL_CALL_SUCCESS;
  bit32                bufAddrUpper = 0;
  bit32                bufAddrLower = 0;
  tdFWProfile_t        *fwProfile;

  void                 *osMemHandle = agNULL;
  void                 *buffer = agNULL;
  agsaFwProfile_t     fwProfileInfo = {0};

  tdsaRoot_t           *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t           *agRoot = &tdsaAllShared->agRootInt;

  fwProfile = (tdFWProfile_t *)&agIOCTLPayload->FunctionSpecificArea[0];


  fwProfileInfo.processor = fwProfile->processor;
  fwProfileInfo.cmd = fwProfile->cmd;
  fwProfileInfo.len = fwProfile->len;
  fwProfileInfo.tcid = fwProfile->tcid;
  if(fwProfile->cmd == START_CODE_PROFILE)
  {
    fwProfileInfo.codeStartAdd = fwProfile->codeStartAdd;
      fwProfileInfo.codeEndAdd = fwProfile->codeEndAdd;
  }
  if((fwProfile->cmd == STOP_TIMER_PROFILE) || (fwProfile->cmd == STOP_CODE_PROFILE))
  {
    if(fwProfile->len != 0)
    {
      if(ostiAllocMemory( tiRoot,
              &osMemHandle,
              (void **)&buffer,
              &bufAddrUpper,
              &bufAddrLower,
              8,
              fwProfile->len,
              agFALSE))
        {
          return IOCTL_CALL_FAIL;
        }
      osti_memset((void *)buffer, 0, fwProfile->len);
    }
    fwProfileInfo.agSgl.sgLower = bufAddrLower;
    fwProfileInfo.agSgl.sgUpper = bufAddrUpper;
    fwProfileInfo.agSgl.len = fwProfile->len;
    fwProfileInfo.agSgl.extReserved = 0;
    tdsaAllShared->tdFWProfileEx.buffer = osMemHandle;
    tdsaAllShared->tdFWProfileEx.virtAddr = buffer;
    tdsaAllShared->tdFWProfileEx.len = fwProfile->len;
  }
  tdsaAllShared->tdFWProfileEx.tdFWProfile = fwProfile;
  tdsaAllShared->tdFWProfileEx.param1 = agParam1;
  tdsaAllShared->tdFWProfileEx.param2 = agParam2;
  tdsaAllShared->tdFWProfileEx.payload = agIOCTLPayload;
  tdsaAllShared->tdFWProfileEx.inProgress = 1;
  status = saFwProfile(agRoot,
            agNULL,
            0,
            &fwProfileInfo
            );
  if(status)
  {
    if((fwProfile->cmd == STOP_TIMER_PROFILE) || (fwProfile->cmd == STOP_CODE_PROFILE))
      ostiFreeMemory(tiRoot, osMemHandle, fwProfile->len);
    status = IOCTL_CALL_FAIL;
  }
  else
    status = IOCTL_CALL_PENDING;
  return status;
}


#endif

/*****************************************************************************
*
* tdipFWControlIoctl
*
* Purpose:  This routine is called to process the FW control IOCTL function.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32 tdipFWControlIoctl(
  tiRoot_t            *tiRoot,
  tiIOCTLPayload_t    *agIOCTLPayload,
  void                *agParam1,
  void                *agParam2,
  void                *agParam3
  ) {

  bit32               status = IOCTL_CALL_PENDING;
  bit32               bufAddrUpper = 0;
  bit32               bufAddrLower = 0;
  tdFWControl_t      *fwControl;
  void               *osMemHandle = agNULL;
  void               *buffer = agNULL;
  agsaUpdateFwFlash_t flashUpdateInfo;
  tdsaRoot_t         *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t      *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t         *agRoot = &tdsaAllShared->agRootInt;

  if( agIOCTLPayload->Length <
      ( agFieldOffset(tiIOCTLPayload_t, FunctionSpecificArea) +
        sizeof(tdFWControl_t) ) )  {
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
    status = IOCTL_CALL_FAIL;
    return status;
  }
  fwControl = (tdFWControl_t *)&agIOCTLPayload->FunctionSpecificArea[0];

  if(fwControl->len != 0)
  {
    if(ostiAllocMemory( tiRoot,
                        &osMemHandle,
                        (void **)&buffer,
                        &bufAddrUpper,
                        &bufAddrLower,
                        8,
                        fwControl->len,
                        agFALSE) )
      return IOCTL_CALL_FAIL;
  }
  osti_memset( (void *)buffer, 0, fwControl->len );
  osti_memcpy( (void *)buffer,
               fwControl->buffer,
               fwControl->len );
  flashUpdateInfo.agSgl.sgLower = bufAddrLower;
  flashUpdateInfo.agSgl.sgUpper = bufAddrUpper;
  flashUpdateInfo.agSgl.len     = fwControl->len;
  flashUpdateInfo.agSgl.extReserved  = 0;
  flashUpdateInfo.currentImageOffset = fwControl->offset;
  flashUpdateInfo.currentImageLen    = fwControl->len;
  flashUpdateInfo.totalImageLen      = fwControl->size;
  switch (agIOCTLPayload->MinorFunction)
  {
    case IOCTL_MN_FW_DOWNLOAD_DATA:
    {
      TI_DBG6(("tdipFWControlIoctl: calling saFwFlashUpdate\n"));
      tdsaAllShared->tdFWControlEx.tdFWControl = fwControl;
      tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
      tdsaAllShared->tdFWControlEx.param1 = agParam1;
      tdsaAllShared->tdFWControlEx.param2 = agParam2;
      tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
      tdsaAllShared->tdFWControlEx.inProgress = 1;
      status = saFwFlashUpdate( agRoot,
                                agNULL,
                                0,
                                &flashUpdateInfo );
      if(status) {
        status = IOCTL_CALL_FAIL;
        fwControl->retcode = IOCTL_CALL_TIMEOUT;
      }
      else {
        status = IOCTL_CALL_PENDING;
      }
      break;
    }
    default:
      status = IOCTL_CALL_INVALID_CODE;
      TI_DBG1( ("tdipFWControlIoctl: ERROR: Wrong IOCTL code %d\n",
                agIOCTLPayload->MinorFunction) );
      ostiFreeMemory(tiRoot, osMemHandle, fwControl->len);
      return status;
  } /* end IOCTL switch */
  return status;
} /* tdipFWControlIoctl */


/*****************************************************************************
*
* tiCOMMgntIOCTL
*
* Purpose:  This routine is a TISA API for processing the PMC specific
*           IOCTL function.
*
*           Each IOCTL function is identified by the IOCTL header
*           specified in the data payload as the following:
*           Field                 Description
*           -----                 -----------
*           Signature             PMC IOCTL signature.
*                                 #define PMC_IOCTL_SIGNATURE   0x1234
*           MajorFunction         Major function number.
*           MinorFunction         Minor function number.
*           Length                Length of this structure in bytes.
*           Status                Return status for this IOCTL function.
*           FunctionSpecificArea  Variable length function specific area.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*   IOCTL_CALL_INVALID_DEVICE Invalid target or destination device.
*
* Note:
*  Used ostiAllocMemory() OS layer callback function to allocate memory
*  for DMA operaion. Then use ostiFreeMemory() to deallocate the memory.
*
*****************************************************************************/
osGLOBAL bit32
tiCOMMgntIOCTL(
               tiRoot_t            *tiRoot,
               tiIOCTLPayload_t    *agIOCTLPayload,
               void                *agParam1,
               void                *agParam2,
               void                *agParam3
               )
{
  bit32                     status = IOCTL_CALL_INVALID_CODE;
  tdsaRoot_t                *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t             *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t                *agRoot = &(tdsaAllShared->agRootNonInt);
  bit32                     EventLogLength = 0;
  bit32                     EventLogOption;
  bit32                     ReadLength = 0;
  bit32                     Offset = 0;
  bit32                     RequestLength = 0;  /* user request on how much data to pass to application */
  agsaContext_t		    *agContext = NULL;
  bit8                      *loc = NULL;

  TI_DBG3(("tiCOMMgntIOCTL: start\n"));

  TI_DBG3(("tiCOMMgntIOCTL: tiRoot %p agIOCTLPayload %p agParam1 %p agParam2 %p agParam3 %p\n",
                            tiRoot,agIOCTLPayload,agParam1,agParam2,agParam3 ));

  TI_DBG3(("tiCOMMgntIOCTL: Signature %X\ntiCOMMgntIOCTL: MajorFunction 0x%X\ntiCOMMgntIOCTL: MinorFunction 0x%X\ntiCOMMgntIOCTL: Length 0x%X\ntiCOMMgntIOCTL: Status 0x%X\ntiCOMMgntIOCTL: Reserved 0x%X\ntiCOMMgntIOCTL: FunctionSpecificArea 0x%X\n",
                           agIOCTLPayload->Signature,
                           agIOCTLPayload->MajorFunction,
                           agIOCTLPayload->MinorFunction,
                           agIOCTLPayload->Length,
                           agIOCTLPayload->Status,
                           agIOCTLPayload->Reserved,
                           agIOCTLPayload->FunctionSpecificArea[0] ));

  /* PMC IOCTL signatures matched ? */
  if(agIOCTLPayload->Signature != PMC_IOCTL_SIGNATURE)
  {
    TI_DBG1(("tiCOMMgntIOCTL:agIOCTLPayload->Signature %x IOCTL_CALL_INVALID_CODE\n",agIOCTLPayload->Signature ));
    status = IOCTL_CALL_INVALID_CODE;
    return (status);
  }

  switch (agIOCTLPayload->MajorFunction)
  {
//TODO: make the card identification more robust. For now - just to keep going with FW download
#ifdef IOCTL_INTERRUPT_TIME_CONFIG
  case IOCTL_MJ_CARD_PARAMETER:
  {
    switch( agIOCTLPayload->MinorFunction )
    {
      case  IOCTL_MN_CARD_GET_INTERRUPT_CONFIG:
      {
          agsaInterruptConfigPage_t *pInterruptConfig = (agsaInterruptConfigPage_t *)&agIOCTLPayload->FunctionSpecificArea[0];
          status = saGetControllerConfig(agRoot,
                                0,
                                AGSA_INTERRUPT_CONFIGURATION_PAGE,
                                pInterruptConfig->vectorMask0,
                                pInterruptConfig->vectorMask1,
                                agParam2);
          if(status == AGSA_RC_SUCCESS) {
              status = IOCTL_CALL_PENDING;
              agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
          } else {
              agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
          }
          break;
      }
      case  IOCTL_MN_CARD_GET_TIMER_CONFIG:
          status = saGetControllerConfig(agRoot, 0, AGSA_SAS_PROTOCOL_TIMER_CONFIG_PAGE, 0, 0, agParam2);
          if(status == AGSA_RC_SUCCESS) {
              status = IOCTL_CALL_PENDING;
              agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
          } else {
              agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
          }
          break;
    }
    break;
  }
#endif /* IOCTL_INTERRUPT_TIME_CONFIG */
  case IOCTL_MJ_INI_DRIVER_IDENTIFY:
  {
    status=IOCTL_CALL_SUCCESS;
    break;
  }
  case IOCTL_MJ_GET_DEVICE_LUN:
		status = tdsaGetNumOfLUNIOCTL(tiRoot,agIOCTLPayload, agParam1, agParam2, agParam3);	
    	if(status == IOCTL_CALL_SUCCESS)
        {
    	  status = IOCTL_CALL_PENDING;
    	}
   break;
case IOCTL_MJ_SMP_REQUEST:
	status = tdsaSendSMPIoctl(tiRoot, agIOCTLPayload,
             	agParam1,agParam2,agParam3);
	break;

  case IOCTL_MJ_FW_CONTROL:
  {
    //ostiIOCTLClearSignal (tiRoot, &agParam1, &agParam2, &agParam3);
    status = tdipFWControlIoctl( tiRoot, agIOCTLPayload,
                                   agParam1, agParam2, agParam3);

    break;
  }
//#ifdef EVENT_LOG_INFO_TESTING
  /* Reserved field in tiIOCTLPayload_t is used as offset */
  case IOCTL_MJ_GET_EVENT_LOG1:
  {
    switch (agIOCTLPayload->MinorFunction)
    {
      case IOCTL_MN_FW_GET_TRACE_BUFFER:
      {
        agsaControllerEventLog_t EventLog;
        saGetControllerEventLogInfo(agRoot, &EventLog);
        TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_GET_EVENT_LOG1 Length %d\n", agIOCTLPayload->Length));
        RequestLength = agIOCTLPayload->Length;
        Offset = agIOCTLPayload->Reserved;
        EventLogLength = EventLog.eventLog1.totalLength;
        EventLogOption = EventLog.eventLog1Option;
        if (EventLogLength <= Offset)
        {
          TI_DBG1(("tiCOMMgntIOCTL: 1 out of range Requestlength %d Offset %d event log length %d\n", RequestLength, Offset, EventLogLength));
          // out of range
          agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA;
          agIOCTLPayload->Length = 0;
          if(EventLogOption == 0)
          {
            agIOCTLPayload->Status = IOCTL_ERR_FW_EVENTLOG_DISABLED;
          }
          status=IOCTL_CALL_SUCCESS;
          return status;
         }
        ReadLength = MIN(EventLogLength - Offset, RequestLength);
        loc = (bit8 *)EventLog.eventLog1.virtPtr + Offset;
        osti_memcpy(&(agIOCTLPayload->FunctionSpecificArea), loc, ReadLength);
      //   tdhexdump("IOCTL_MJ_GET_EVENT_LOG1 first 32bytes", (bit8 *)&(agIOCTLPayload->FunctionSpecificArea), 32);
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
        agIOCTLPayload->Length = (bit16)ReadLength;
        status=IOCTL_CALL_SUCCESS;
        break;
     }
     case IOCTL_MN_FW_GET_EVENT_FLASH_LOG1:
     {
       TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MN_FW_GET_EVENT_FLASH_LOG1\n"));
       status = tdsaRegDumpGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
       break;
     }
   }
   break;
  }

  case IOCTL_MJ_GET_EVENT_LOG2:
  {
    switch (agIOCTLPayload->MinorFunction)
    {
      case IOCTL_MN_FW_GET_TRACE_BUFFER:
      {
        agsaControllerEventLog_t EventLog;
        saGetControllerEventLogInfo(agRoot, &EventLog);
        TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_GET_EVENT_LOG2 Length %d\n", agIOCTLPayload->Length));
        RequestLength = agIOCTLPayload->Length;
        Offset = agIOCTLPayload->Reserved;
        EventLogLength = EventLog.eventLog2.totalLength;
        EventLogOption = EventLog.eventLog2Option;
        if (EventLogLength <= Offset)
        {
          TI_DBG1(("tiCOMMgntIOCTL: 2 out of range Requestlength %d Offset %d event log length %d\n", RequestLength, Offset, EventLogLength));
          /* out of range */
          agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA;
          agIOCTLPayload->Length = 0;
          if(EventLogOption == 0)
          {
            agIOCTLPayload->Status = IOCTL_ERR_FW_EVENTLOG_DISABLED;
          }
          status=IOCTL_CALL_SUCCESS;
          return status;
        }
        ReadLength = MIN(EventLogLength - Offset, RequestLength);
        loc = (bit8 *)EventLog.eventLog2.virtPtr + Offset;
        osti_memcpy(&(agIOCTLPayload->FunctionSpecificArea), loc, ReadLength);
    //    tdhexdump("IOCTL_MJ_GET_EVENT_LOG2 first 32bytes", (bit8 *)&(agIOCTLPayload->FunctionSpecificArea), 32);
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
        agIOCTLPayload->Length = (bit16)ReadLength;
        status=IOCTL_CALL_SUCCESS;
        break;
      }
      case IOCTL_MN_FW_GET_EVENT_FLASH_LOG2:
      {
        TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MN_FW_GET_EVENT_FLASH_LOG2\n"));
        status = tdsaRegDumpGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
        break;
      }
    }
    break;
  }


  case IOCTL_MJ_FW_INFO:
  {
    agsaControllerInfo_t ControllerInfo;
    saGetControllerInfo(agRoot, &ControllerInfo);
    TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_FW_INFO Length %d\n", agIOCTLPayload->Length));
    RequestLength = agIOCTLPayload->Length;
    Offset = agIOCTLPayload->Reserved;
    if (RequestLength == 0)
    {
      TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_FW_INFO: No more Data!\n"));
      /* out of range */
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA;
      agIOCTLPayload->Length = 0;
      status=IOCTL_CALL_SUCCESS;
      return status;
    }

    osti_memcpy((bit8*)&(agIOCTLPayload->FunctionSpecificArea), (bit8*)&ControllerInfo, sizeof(agsaControllerInfo_t));

    TI_DBG1(("tiCOMMgntIOCTL:IOCTL_MJ_FW_INFO ControllerInfo signature 0x%X\n",ControllerInfo.signature));
    TI_DBG1(("tiCOMMgntIOCTL:IOCTL_MJ_FW_INFO ControllerInfo PCILinkRate 0x%X\n",ControllerInfo.PCILinkRate));
    TI_DBG1(("tiCOMMgntIOCTL:IOCTL_MJ_FW_INFO ControllerInfo PCIWidth 0x%X\n",ControllerInfo.PCIWidth));
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
    status=IOCTL_CALL_SUCCESS;
    break;

  }

  case IOCTL_MJ_GET_FW_REV:
  {
    agsaControllerInfo_t ControllerInfo;
    saGetControllerInfo(agRoot, &ControllerInfo);
    TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_FW_REV Length %d\n", agIOCTLPayload->Length));
    RequestLength = agIOCTLPayload->Length;
    Offset = agIOCTLPayload->Reserved;
    if (RequestLength == 0)
    {
      TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_GET_FW_REV: No more Data!\n"));
      /* out of range */
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA;
      agIOCTLPayload->Length = 0;
      status=IOCTL_CALL_SUCCESS;
      return status;
    }

    osti_memcpy((bit8*)&(agIOCTLPayload->FunctionSpecificArea), (bit8*)&ControllerInfo.fwRevision, sizeof(bit32));
    loc = (bit8 *)&(agIOCTLPayload->FunctionSpecificArea)+ sizeof(bit32);
    osti_memcpy(loc, (bit8*)&ControllerInfo.sdkRevision, sizeof(bit32));

    agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
    status=IOCTL_CALL_SUCCESS;
    break;

  }

#ifdef SPC_ENABLE_PROFILE
  case IOCTL_MJ_FW_PROFILE:
  {
    TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_FW_PROFILE\n"));
    status = tdipFWProfileIoctl( tiRoot, agIOCTLPayload,
                                   agParam1, agParam2, agParam3);
    break;
  }
#endif /* SPC_ENABLE_PROFILE */

  case IOCTL_MJ_GET_CORE_DUMP:
  {
    TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_GET_CORE_DUMP\n"));
    if (tiIS_SPC(agRoot))
    {
      status = tdsaRegDumpGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
    }
    else
    {
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_SUPPORTED;
      status = IOCTL_CALL_SUCCESS;
    }
    break;
  }
//#endif
  case IOCTL_MJ_NVMD_SET:
  {
    bit8 nvmDev;
    TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_NVMD_SET\n"));
    nvmDev = (bit8) agIOCTLPayload->Status;
    agIOCTLPayload->Status = 0;
    status = tdsaNVMDSetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, &nvmDev);
	break;
	}
#if 0
case IOCTL_MJ_GPIO: 
  {
    bit32 sVid =0;
    TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_GPIO\n"));

    /* Get Subsystem vendor  */
    sVid = ostiChipConfigReadBit32(tiRoot,0x2C);
    sVid = sVid & 0xFFFF;

    /* GPIO is only intended for chip down design 
     * therefore it's only applies to 8H/SPCv product family 
     */
    if(sVid == 0x9005)
    return IOCTL_CALL_INVALID_DEVICE;
    
    status = tdsaGpioSetup(tiRoot, agContext, agIOCTLPayload, agParam1, agParam2);
    if(status == IOCTL_CALL_SUCCESS)  
        status = IOCTL_CALL_PENDING; /* Wait for response from the Controller */
    else 
      return status;  

    break;
  }
#endif
  
  case IOCTL_MJ_SGPIO:
  {
    TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_SGPIO\n"));
    status = tdsaSGpioIoctlSetup(tiRoot, agContext, agIOCTLPayload, agParam1, agParam2);
    break;
  }

  case IOCTL_MJ_NVMD_GET:
  {
    bit8 nvmDev;
    TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_NVMD_GET\n"));
    nvmDev = (bit8) agIOCTLPayload->Status;
    agIOCTLPayload->Status = 0;
    status = tdsaNVMDGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, &nvmDev);
    break;
  }

  case IOCTL_MJ_GET_FORENSIC_DATA:
  {
    TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_FORENSIC_DATA\n"));
    status = tdsaForensicDataGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
    break;
  }
  case IOCTL_MJ_GET_DEVICE_INFO:
  {
    TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_DEVICE_INFO\n"));
    status = tdsaDeviceInfoGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
    break;
  }

  case IOCTL_MJ_GET_IO_ERROR_STATISTIC:
  {
    TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_IO_ERROR_STATISTIC\n"));
    status = tdsaIoErrorStatisticGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
    break;
  }

  case IOCTL_MJ_GET_IO_EVENT_STATISTIC:
  {
    TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_IO_EVENT_STATISTIC\n"));
    status = tdsaIoEventStatisticGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
    break;
  }

  case IOCTL_MJ_SEND_BIST:
  {
    TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_SEND_BIST\n"));
    status = tdsaSendBISTIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
    break;
  }

#if 0 
  case IOCTL_MJ_SET_OR_GET_REGISTER:
  {
    TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_SET_OR_GET_REGISTER\n"));
    status = tdsaRegisterIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
    break;
  }
  
#endif
   case IOCTL_MJ_PHY_DETAILS:
   {
	PhyDetails_t  *PhyDetails = (PhyDetails_t*)&agIOCTLPayload->FunctionSpecificArea;
        agsaRoot_t  *agRoot = &(tdsaAllShared->agRootNonInt);
        agsaLLRoot_t  *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 	
	bit8  *sasAddressHi;
	bit8  *sasAddressLo;
	bit8  sas_dev_type;
	int i = 0;

	tiIniGetDirectSataSasAddr(tiRoot, i , &sasAddressHi, &sasAddressLo);
	for( i = 0; i < saRoot->phyCount ; i++)
        {	
		PhyDetails[i].attached_phy = saRoot->phys[i].sasIdentify.phyIdentifier;
		/* deice types
 		 * SAS	 
 		 * 0x01 - Sas end device   
 		 * 0x02 - Expander device 
 		 * SATA
 		 * 0x11 - Sata
 		 * NO DEVICE 0x00
 		 */
		sas_dev_type = (saRoot->phys[i].sasIdentify.deviceType_addressFrameType & 0x70 ) >> 4 ;
		if ((saRoot->phys[i].status == 1) && (sas_dev_type == 0)){ //status 1 - Phy Up 
			//Sata phy 
			PhyDetails[i].attached_dev_type = SAS_PHY_SATA_DEVICE;//0x11 for sata end device
			osti_memcpy(&PhyDetails[i].attached_sasAddressHi, tdsaAllShared->Ports[i].SASID.sasAddressHi, sizeof(bit32));
			osti_memcpy(&PhyDetails[i].attached_sasAddressLo, tdsaAllShared->Ports[i].SASID.sasAddressLo, sizeof(bit32));
			PhyDetails[i].attached_sasAddressLo[3] += i + 16; 
		}	
		else {
			PhyDetails[i].attached_dev_type = sas_dev_type;
	        	osti_memcpy(&PhyDetails[i].attached_sasAddressHi, saRoot->phys[i].sasIdentify.sasAddressHi, sizeof(bit32));
			osti_memcpy(&PhyDetails[i].attached_sasAddressLo, saRoot->phys[i].sasIdentify.sasAddressLo, sizeof(bit32));
		}
		osti_memcpy(&PhyDetails[i].sasAddressLo,&(tdsaAllShared->Ports[i].SASID.sasAddressLo), sizeof(bit32));
		osti_memcpy(&PhyDetails[i].sasAddressHi,&(tdsaAllShared->Ports[i].SASID.sasAddressHi), sizeof(bit32));
	}

//    	osti_memcpy(&agIoctlPayload->FunctionSpecificArea,&PhyInfo, sizeof(agsaSGpioReqResponse_t));
//	printk("Ioctl success\n");
	return IOCTL_CALL_SUCCESS;		
   }

   case IOCTL_MJ_PHY_GENERAL_STATUS:
 	  {
		agsaPhyGeneralState_t     *PhyData=NULL;
		bit32					   ret = AGSA_RC_FAILURE;
  		PhyData = (agsaPhyGeneralState_t*) &agIOCTLPayload->FunctionSpecificArea[0];

        PhyData->Reserved2 = 0;
        /* Validate the length */
        if (agIOCTLPayload->Length < sizeof(agsaPhyGeneralState_t))
        {
          status = IOCTL_CALL_FAIL;
          break;
        }
 
        tdsaAllShared->tdFWControlEx.param1 = agParam1;
        tdsaAllShared->tdFWControlEx.param2 = agParam2;
        tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
        tdsaAllShared->tdFWControlEx.inProgress = 1;
	//tdsaAllShared->tdFWControlEx.usrAddr = PhyData;

    	ret = tdsaGetPhyGeneralStatusIoctl(tiRoot,PhyData);
    	if(ret == AGSA_RC_FAILURE)
        {
    	  status = IOCTL_CALL_FAIL;
		  tdsaAllShared->tdFWControlEx.payload = NULL; 
		  tdsaAllShared->tdFWControlEx.inProgress = 0;
		  break;
    	}
		else if(ret == IOCTL_ERR_STATUS_NOT_SUPPORTED)
		{

		  agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_SUPPORTED;
		  status = IOCTL_CALL_SUCCESS;
		  break;
		}

    	//status = IOCTL_CALL_PENDING;
    	status = IOCTL_CALL_PENDING;
     }

   break;
#if 1 
  case IOCTL_MJ_GET_PHY_PROFILE:
  {
    TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_GET_PHY_PROFILE %p %p %p\n",agParam1,agParam2,agParam3));
    status = tdsaPhyProfileIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3);
    break;
  }
#endif
  case IOCTL_MJ_LL_TRACING:
  {
    void * stu = &agIOCTLPayload->FunctionSpecificArea[0];
    switch(agIOCTLPayload->MinorFunction)
    {

      case IOCTL_MN_LL_RESET_TRACE_INDEX:
      {

#ifdef SA_ENABLE_TRACE_FUNCTIONS
        TSTMTID_TRACE_BUFFER_RESET *llist = (TSTMTID_TRACE_BUFFER_RESET *)stu;
        hpTraceBufferParms_t  BufferParms;
        TI_DBG5(("tdReturnIOCTL_Info: hpIOCTL_ResetTraceIndex\n"));

        BufferParms.TraceCompiled  = 0;
        BufferParms.TraceWrap      = 0;
        BufferParms.CurrentTraceIndexWrapCount = 0;
        BufferParms.BufferSize     = 0;
        BufferParms.CurrentIndex   = 0;
        BufferParms.pTrace         = NULL;
        BufferParms.pTraceIndexWrapCount        = NULL;
        BufferParms.pTraceMask     = NULL;
        BufferParms.pCurrentTraceIndex  = NULL;

        smTraceGetInfo(agRoot,&BufferParms);
        TI_DBG5(("tdReturnIOCTL_Info: pTrace                %p\n",BufferParms.pTrace));
        TI_DBG5(("tdReturnIOCTL_Info: pCurrentTraceIndex    %p %X\n",BufferParms.pCurrentTraceIndex,*BufferParms.pCurrentTraceIndex));
        TI_DBG5(("tdReturnIOCTL_Info: pTraceIndexWrapCount  %p %X\n",BufferParms.pTraceIndexWrapCount,*BufferParms.pTraceIndexWrapCount));
        TI_DBG5(("tdReturnIOCTL_Info: pTraceMask            %p %X\n",BufferParms.pTraceMask,*BufferParms.pTraceMask));

        if( llist->Flag != 0)
        {
          if( llist->TraceMask != *BufferParms.pTraceMask)
          {
            smTraceSetMask(agRoot,  llist->TraceMask );
          }
        }
        if( llist->Reset)
        {

          *BufferParms.pCurrentTraceIndex = 0;
          smResetTraceBuffer(agRoot);

          *BufferParms.pCurrentTraceIndex = 0;
          *BufferParms.pTraceIndexWrapCount =0;
          llist->TraceMask = *BufferParms.pTraceMask;
        }
#endif  /* SA_ENABLE_TRACE_FUNCTIONS  */
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
        status = IOCTL_CALL_SUCCESS;

      }
      break;

    case IOCTL_MN_LL_GET_TRACE_BUFFER_INFO:
      {
        hpTraceBufferParms_t  BufferParms;
        TSTMTID_TRACE_BUFFER_INFO *llist = (TSTMTID_TRACE_BUFFER_INFO *)stu;
        TI_DBG5(("tdReturnIOCTL_Info: hpIOCTL_GetTraceBufferInfo\n"));


        BufferParms.TraceCompiled  = 0;
        BufferParms.TraceWrap      = 0;
        BufferParms.CurrentTraceIndexWrapCount = 0;
        BufferParms.BufferSize     = 0;
        BufferParms.CurrentIndex   = 0;
        BufferParms.pTrace         = NULL;
        BufferParms.pTraceMask     = NULL;
#ifdef SA_ENABLE_TRACE_FUNCTIONS
        smTraceGetInfo(agRoot,&BufferParms);
#endif  /* SA_ENABLE_TRACE_FUNCTIONS not enabled */
        llist->TraceCompiled = BufferParms.TraceCompiled;
        llist->BufferSize = BufferParms.BufferSize;
        llist->CurrentIndex = BufferParms.CurrentIndex ;
        llist->CurrentTraceIndexWrapCount =  BufferParms.CurrentTraceIndexWrapCount;
        llist->TraceWrap = BufferParms.TraceWrap;
        if(BufferParms.pTraceMask != NULL)
        {
          llist->TraceMask = *BufferParms.pTraceMask;
        }
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
        status = IOCTL_CALL_SUCCESS;
      }
      break;

    case IOCTL_MN_LL_GET_TRACE_BUFFER:
      {
#ifdef SA_ENABLE_TRACE_FUNCTIONS
        TSTMTID_TRACE_BUFFER_FETCH *llist = (TSTMTID_TRACE_BUFFER_FETCH *)stu;

        hpTraceBufferParms_t  BufferParms;
        bit32 c= 0;

        BufferParms.TraceCompiled  = 0;
        BufferParms.TraceWrap      = 0;
        BufferParms.CurrentTraceIndexWrapCount = 0;
        BufferParms.BufferSize     = 0;
        BufferParms.CurrentIndex   = 0;
        BufferParms.pTrace         = NULL;
        smTraceGetInfo(agRoot,&BufferParms);

        TI_DBG6(("tdReturnIOCTL_Info: hpIOCTL_GetTraceBuffer\n"));

        if(llist->LowFence != LowFence32Bits)
        {
          break;
        }
        if(llist->HighFence != HighFence32Bits)
        {
          break;
        }

        if(llist->BufferOffsetBegin + FetchBufferSIZE > BufferParms.BufferSize  )
        {
        }

        for ( c=0; c < FetchBufferSIZE;c++)
        {
          llist->Data[c] = *(BufferParms.pTrace+( c + llist->BufferOffsetBegin));
        }
#endif  /* SA_ENABLE_TRACE_FUNCTIONS not enabled */
      }
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
      status = IOCTL_CALL_SUCCESS;
      break;
    }
    break;
  }

#ifdef SA_LL_API_TEST
  case IOCTL_MJ_LL_API_TEST:
  {
    status = tdLlApiTestIoctl( tiRoot, agIOCTLPayload,
               agParam1,agParam2,agParam3 );
    break;
  }

#endif /* SA_LL_API_TEST */

  case IOCTL_MJ_MODE_CTL_PAGE:
  {
    /* The SPCv controller has some options accessed via mode pages */
    tiEncryptDekConfigPage_t *pModePage= (tiEncryptDekConfigPage_t *) &agIOCTLPayload->FunctionSpecificArea[0];
    bit32 pageLength = 0;
    bit32 pageCode;
    bit32 modeOperation;

    pageCode = pModePage->pageCode & 0xFF;
    modeOperation = *(bit32 *) agParam2;

    switch(modeOperation)
    {

      case tiModePageSet:
        switch (pageCode)
        {
          case TI_ENCRYPTION_DEK_CONFIG_PAGE:
            pageLength = sizeof(tiEncryptDekConfigPage_t);
            break;

          case TI_ENCRYPTION_CONTROL_PARM_PAGE:
            pageLength = sizeof(tiEncryptControlParamPage_t);
            break;

          case TI_ENCRYPTION_GENERAL_CONFIG_PAGE:
            /* Pages are currently unsupported */
            pageLength = 0;
            break;
        }

        status = saSetControllerConfig(agRoot, 0, pageCode, pageLength, pModePage, (agsaContext_t *)agIOCTLPayload);
        break;

      case tiModePageGet:
        status = saGetControllerConfig(agRoot, 0, pageCode, 0, 0, (agsaContext_t *)agIOCTLPayload);
        break;

      default:
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_SUPPORTED;
    }
  }
    break;
#ifdef PHY_RESTART_TEST
    case IOCTL_MJ_PORT_START:
    {
      bit32 portID, tiStatus;
      bit32 *data = (bit32*) &agIOCTLPayload->FunctionSpecificArea[0];
      portID = *data;

      tiStatus = tiCOMPortStart(tiRoot, portID, tdsaAllShared->Ports[portID].tiPortalContext, 0);

      if (tiStatus == tiSuccess)
      {
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
      }
      else
      {
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
      }
      status = IOCTL_CALL_SUCCESS;
      break;
    }

    case IOCTL_MJ_PORT_STOP:
    {
      bit32 portID, tiStatus;
      bit32 *data = (bit32*) &agIOCTLPayload->FunctionSpecificArea[0];
      portID =  *data;

      tiStatus = tiCOMPortStop(tiRoot, tdsaAllShared->Ports[portID].tiPortalContext);
      if (tiStatus == tiSuccess)
      {
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
      }
      else
      {
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
      }

      status = IOCTL_CALL_SUCCESS;
      break;
    }
#endif
 case IOCTL_MJ_SEND_TMF:
       switch(agIOCTLPayload->MinorFunction)
	{
	     case IOCTL_MN_TMF_DEVICE_RESET:
		status = tdsaSendTMFIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, AG_TARGET_WARM_RESET);
	        break;
	     case IOCTL_MN_TMF_LUN_RESET:
	 	status = tdsaSendTMFIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, AG_LOGICAL_UNIT_RESET);
		break;
	}
	break;
 case IOCTL_MJ_GET_DRIVER_VERSION:
        osti_sprintf(agIOCTLPayload->FunctionSpecificArea, "%s", AGTIAPI_DRIVER_VERSION);
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
        status=IOCTL_CALL_SUCCESS;
	break;
  default:
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_SUPPORTED;
    break;
  }

  return status;
}

#if 0
/*****************************************************************************
*
* tdsaGpioSetup 
*
* Purpose:  This routine is called to set Gpio parameters to the controller.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agsaContext_t :
*   tiIOCTLPayload_t :  ioctl header with payload gpio info 
*   agParam1,agParam2 :  Generic parameters
*
* Return: status
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaGpioSetup(
                tiRoot_t            *tiRoot,
                agsaContext_t       *agContext,
                tiIOCTLPayload_t    *agIOCTLPayload,
                void                *agParam1,
                void                *agParam2
                )
{

  tdsaTimerRequest_t        *osIoctlTimer;
  agsaGpioEventSetupInfo_t  *gpioEventSetupInfo;
  agsaGpioWriteSetupInfo_t  *gpioWriteSetupInfo;
  agsaGpioPinSetupInfo_t    *gpioPinSetupInfo;
  tdsaRoot_t                *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t             *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t                *agRoot = &(tdsaAllShared->agRootInt);
  bit32                     status = IOCTL_CALL_SUCCESS;

  TI_DBG3(("tdsaGpioSetup: start\n"));

  if(tiRoot == agNULL || agIOCTLPayload == agNULL )
  return IOCTL_CALL_FAIL;

  osIoctlTimer = &tdsaAllShared->osIoctlTimer;
  tdsaInitTimerRequest(tiRoot, osIoctlTimer);
  tdIoctlStartTimer(tiRoot, osIoctlTimer); /* Start the timout handler for both ioctl and controller response */
  tdsaAllShared->tdFWControlEx.virtAddr = (bit8 *)osIoctlTimer;

  tdsaAllShared->tdFWControlEx.usrAddr = (bit8 *)&agIOCTLPayload->FunctionSpecificArea[0];
  tdsaAllShared->tdFWControlEx.param1 = agParam1;
  tdsaAllShared->tdFWControlEx.param2 = agParam2;
  tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
  tdsaAllShared->tdFWControlEx.inProgress = 1;

    switch (agIOCTLPayload->MinorFunction)
    {
     
     case IOCTL_MN_GPIO_PINSETUP:
     {
	 TI_DBG3(("tdsaGpioSetup: IOCTL_MN_GPIO_PINSETUP\n"));
         gpioPinSetupInfo =(agsaGpioPinSetupInfo_t *)&agIOCTLPayload->FunctionSpecificArea[0];
         status = saGpioPinSetup(agRoot, agContext, 0, gpioPinSetupInfo);

         break;
     }	 
     case IOCTL_MN_GPIO_EVENTSETUP:
     {
	TI_DBG3(("tdsaGpioSetup: IOCTL_MN_GPIO_EVENTSETUP\n"));
        gpioEventSetupInfo = (agsaGpioEventSetupInfo_t  *)&agIOCTLPayload->FunctionSpecificArea[0];
        status = saGpioEventSetup(agRoot, agContext, 0, gpioEventSetupInfo);

        break;
     }
   	
     case IOCTL_MN_GPIO_READ:
     {
	 TI_DBG3(("tdsaGpioSetup: IOCTL_MN_GPIO_READ\n"));
         status = saGpioRead(agRoot, agContext, 0);

        break;
     }   	 	 

     case IOCTL_MN_GPIO_WRITE:
     {
	 TI_DBG3(("tdsaGpioSetup: IOCTL_MN_GPIO_WRITE\n"));
         gpioWriteSetupInfo = (agsaGpioWriteSetupInfo_t *)&agIOCTLPayload->FunctionSpecificArea[0];
         status = saGpioWrite(agRoot, agContext, 0, gpioWriteSetupInfo->gpioWritemask, gpioWriteSetupInfo->gpioWriteVal);

         break;
     }
     
     default :
         return status;
    }

    if(status != AGSA_RC_SUCCESS)
    {
      status = IOCTL_CALL_FAIL;
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;

      tdsaSingleThreadedEnter(tiRoot, TD_TIMER_LOCK);
      if (osIoctlTimer->timerRunning == agTRUE)
      {
         tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK);
         tdsaKillTimer(tiRoot, osIoctlTimer);
        
      }else{
         tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK);
      }
    }

    TI_DBG3(("tdsaGpioPinSetup: End\n"));
    return status;

}
#endif

/*****************************************************************************
*
* ostiGetGpioIOCTLRsp
*
* Purpose:  This routine is called for Get Gpio IOCTL reaponse has been received.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   payloadRsp:     Pointer to the FW download IOMB's payload.
*
* Return: none
*
*
*****************************************************************************/

osGLOBAL void  ostiGetGpioIOCTLRsp(
                        tiRoot_t                 *tiRoot,
                        bit32                    status,
                        bit32                    gpioReadValue,
                        agsaGpioPinSetupInfo_t   *gpioPinSetupInfo,
                        agsaGpioEventSetupInfo_t *gpioEventSetupInfo
                        )
{
     tdsaRoot_t                *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
     tdsaContext_t             *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
     tiIOCTLPayload_t          *agIoctlPayload ;
     agsaGpioReadInfo_t        *gpioReadInfo;
      
     tdsaTimerRequest_t        *osIoctlTimer;
	 osIoctlTimer = (tdsaTimerRequest_t *)tdsaAllShared->tdFWControlEx.virtAddr;         

     TI_DBG2(("ostiGetGpioIOCTLRsp: start, status = %d \n", status));

     agIoctlPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); 
    
     if(agIoctlPayload == agNULL){
        return;  
      }

     agIoctlPayload->Status =(bit16) status;

     if( (status != IOCTL_CALL_TIMEOUT) && (osIoctlTimer != NULL))
     {
        tdsaSingleThreadedEnter(tiRoot, TD_TIMER_LOCK);
        if (osIoctlTimer->timerRunning == agTRUE)
        {
           tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK);
           tdsaKillTimer(tiRoot, osIoctlTimer);
        
        }else{
           tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK);
        }
     }else  {
         tdsaAllShared->tdFWControlEx.inProgress = 0;
         agIoctlPayload->Status = (bit16)status;
         ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1,
                               tdsaAllShared->tdFWControlEx.param2, NULL);
        return; 
     }

     if(status == SUCCESS) 
       TI_DBG3((" ostiGetGpioIOCTLRsp:Got GPIO response from OUTBuf"));
    else {
      tdsaAllShared->tdFWControlEx.inProgress = 0;
      ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1,
                               tdsaAllShared->tdFWControlEx.param2, NULL);
      return;     
    }

    switch (agIoctlPayload->MinorFunction)
     {

     case IOCTL_MN_GPIO_PINSETUP:
      {
       TI_DBG3((" ostiGetGpioIOCTLRsp:Got GPIO response for IOCTL_MN_GPIO_PINSETUP"));

         break;
      }	 
     case IOCTL_MN_GPIO_EVENTSETUP:
     {
       TI_DBG3((" ostiGetGpioIOCTLRsp:Got GPIO response for IOCTL_MN_GPIO_EVENTSETUP"));

         break;
     }

     case IOCTL_MN_GPIO_WRITE:
     {
       TI_DBG3((" ostiGetGpioIOCTLRsp:Got GPIO response for IOCTL_MN_GPIO_WRITE"));

         break;
     }
   	
    case IOCTL_MN_GPIO_READ:
    {
         gpioReadInfo = ( agsaGpioReadInfo_t *)tdsaAllShared->tdFWControlEx.usrAddr;

         gpioReadInfo->gpioReadValue = gpioReadValue;
         gpioReadInfo->gpioInputEnabled = gpioPinSetupInfo->gpioInputEnabled ; /* GPIOIE */
         gpioReadInfo->gpioEventLevelChangePart1 = gpioPinSetupInfo->gpioTypePart1; /* GPIEVCHANGE (pins 11-0) */
         gpioReadInfo->gpioEventLevelChangePart2 = gpioPinSetupInfo->gpioTypePart2; /* GPIEVCHANGE (pins 23-20) */
         gpioReadInfo->gpioEventRisingEdgePart1 = 0xFFF & gpioEventSetupInfo->gpioEventRisingEdge; /* GPIEVRISE (pins 11-0) */
         gpioReadInfo->gpioEventRisingEdgePart2 = 0x00F00000 & (gpioEventSetupInfo->gpioEventRisingEdge); /* GPIEVRISE (pins 23-20) */
         gpioReadInfo->gpioEventFallingEdgePart1 = 0xFFF & gpioEventSetupInfo->gpioEventFallingEdge; /* GPIEVALL (pins 11-0) */
         gpioReadInfo->gpioEventFallingEdgePart2 = 0x00F00000  & gpioEventSetupInfo->gpioEventFallingEdge; /* GPIEVALL (pins 23-20 */

         break;
     }   	 	 
 
    default : 
         break;     
    }

    if(tdsaAllShared->tdFWControlEx.inProgress) 
    {
      tdsaAllShared->tdFWControlEx.inProgress = 0;
      ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1,
                              tdsaAllShared->tdFWControlEx.param2, NULL);
    }
    TI_DBG2(("ostiGetGpioIOCTLRsp: end \n"));

   return ;
}

/*****************************************************************************
*
* tdsaSGpioIoctlSetup 
*
* Purpose:  This routine is called to send SGPIO request to the controller.
*
* Parameters:
*   tiRoot:             Pointer to driver instance
*   agsaContext_t:      Context for this request
*   tiIOCTLPayload_t:   ioctl header with payload sgpio info 
*   agParam1,agParam2:  Generic parameters
*
* Return: status
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaSGpioIoctlSetup(
                tiRoot_t            *tiRoot,
                agsaContext_t       *agContext,
                tiIOCTLPayload_t    *agIOCTLPayload,
                void                *agParam1,
                void                *agParam2
                )
{
  tdsaRoot_t                *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t             *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t                *agRoot = &(tdsaAllShared->agRootInt);
  bit32                     status = IOCTL_CALL_FAIL;
  agsaSGpioReqResponse_t    *pSGpioReq = (agsaSGpioReqResponse_t *)&agIOCTLPayload->FunctionSpecificArea[0];

  TI_DBG3(("tdsaSGpioIoctlSetup: start\n"));
  
  agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
  
  do
  {
    if (tiRoot == agNULL || agIOCTLPayload == agNULL)
    {
      break;
    }
    
    /* Validate the length */
    if (agIOCTLPayload->Length < sizeof(agsaSGpioReqResponse_t))
    {
      TI_DBG3(("Invalid length\n"));
      break;
    }
  
    /* Validate the SMP Frame Type, Function and Register Type fields */
    if ((pSGpioReq->smpFrameType != SMP_REQUEST) || \
        ((pSGpioReq->function != SMP_READ_GPIO_REGISTER) && (pSGpioReq->function != SMP_WRITE_GPIO_REGISTER)) || \
        (pSGpioReq->registerType > AGSA_SGPIO_GENERAL_PURPOSE_TRANSMIT_REG))
    {
      TI_DBG4(("Invalid Parameter\n"));
      break;
    }
		
    /* Specific validation for configuration register type */
    if (AGSA_SGPIO_CONFIG_REG == pSGpioReq->registerType)
    {
      if ((pSGpioReq->registerIndex > 0x01) || \
          ((0x00 == pSGpioReq->registerIndex) && (pSGpioReq->registerCount > 0x02)) || \
          ((0x01 == pSGpioReq->registerIndex) && (pSGpioReq->registerCount > 0x01)))
      {
        break;
      }
    }
  
    /* Use FW control place in shared structure to keep the necessary information */
    tdsaAllShared->tdFWControlEx.param1 = agParam1;
    tdsaAllShared->tdFWControlEx.param2 = agParam2;
    tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
    tdsaAllShared->tdFWControlEx.inProgress = 1;
	  
    status = saSgpio(agRoot, agContext, 0, pSGpioReq);
    if (status != AGSA_RC_SUCCESS)
    {
      break;
    }

    status = IOCTL_CALL_PENDING;

  } while (0);
  
  TI_DBG3(("tdsaGpioPinSetup: End\n"));
  return status;
}

/*****************************************************************************
*
* ostiSgpioIoctlRsp
*
* Purpose:  This routine is called when a SGPIO IOCTL response is received.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   pSgpioResponse: Pointer to the SGPIO response
*
* Return: none
*
*
*****************************************************************************/
osGLOBAL void ostiSgpioIoctlRsp(
                            tiRoot_t                *tiRoot,
                            agsaSGpioReqResponse_t  *pSgpioResponse
                            )
{
  tdsaRoot_t        *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  tiIOCTLPayload_t  *agIoctlPayload = agNULL;

  TI_DBG3(("ostiSgpioIoctlRsp: start\n"));

  if (tdsaAllShared->tdFWControlEx.inProgress) 
  {
    agIoctlPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
    if (agIoctlPayload)
    {
      tdsaAllShared->tdFWControlEx.payload = NULL; 
      osti_memcpy(&agIoctlPayload->FunctionSpecificArea[0], pSgpioResponse, sizeof(agsaSGpioReqResponse_t));
      agIoctlPayload->Status = IOCTL_ERR_STATUS_OK;
      sgpioResponseSet = 1;
    }
	tdsaAllShared->sgpioResponseSet = 1;    //Sunitha:Check if needed?
    
    ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1,
                  tdsaAllShared->tdFWControlEx.param2, agNULL);
                  
    tdsaAllShared->tdFWControlEx.inProgress = 0;
  }

  TI_DBG3(("ostiSgpioIoctlRsp: end\n"));
}
/*****************************************************************************
*
* ostiCOMMgntIOCTLRsp
*
* Purpose:  This routine is called when FW control IOCTL reaponse has been received.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:          Pointer to driver instance
*   payloadRsp:     Pointer to the FW download IOMB's payload.
*
* Return: none
*
*
*
*****************************************************************************/

osGLOBAL void ostiCOMMgntIOCTLRsp(
                        tiRoot_t            *tiRoot,
                        bit32               status
                        )
{
    tdsaRoot_t           *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;

    TI_DBG1(("ostiCOMMgntIOCTLRsp: status 0x%x\n",status));
    (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status;

    ostiFreeMemory(tiRoot,
                   tdsaAllShared->tdFWControlEx.buffer,
                   tdsaAllShared->tdFWControlEx.tdFWControl->len);

    ostiIOCTLSetSignal(tiRoot,
                       tdsaAllShared->tdFWControlEx.param1,
                       tdsaAllShared->tdFWControlEx.param2,
                       NULL);
}


/*****************************************************************************
*
* ostiRegDumpIOCTLRsp
*
* Purpose:  This routine is called when Register Dump from flash IOCTL reaponse has been received.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:          Pointer to driver instance
*   payloadRsp:     Pointer to the FW download IOMB's payload.
*
* Return: none
*
*
*
*****************************************************************************/

osGLOBAL void ostiRegDumpIOCTLRsp(
                        tiRoot_t            *tiRoot,
                        bit32               status
                        )
{
    tdsaRoot_t           *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;

    TI_DBG1(("ostiRegDumpIOCTLRsp: start\n"));
//    (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status;
    osti_memcpy((void *)(tdsaAllShared->tdFWControlEx.usrAddr),
                (void *)(tdsaAllShared->tdFWControlEx.virtAddr),
                tdsaAllShared->tdFWControlEx.len);

    ostiFreeMemory(tiRoot,
                  tdsaAllShared->tdFWControlEx.buffer,
                  tdsaAllShared->tdFWControlEx.len);

    ostiIOCTLSetSignal(tiRoot,
                       tdsaAllShared->tdFWControlEx.param1,
                       tdsaAllShared->tdFWControlEx.param2,
                       NULL);
}

/*****************************************************************************
*
* ostiSetNVMDIOCTLRsp
*
* Purpose:  This routine is called for Set NVMD IOCTL reaponse has been received.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:          Pointer to driver instance
*   payloadRsp:     Pointer to the FW download IOMB's payload.
*
* Return: none
*
*
*
*****************************************************************************/

osGLOBAL void ostiSetNVMDIOCTLRsp(
                        tiRoot_t            *tiRoot,
                        bit32               status
                        )
{
    tdsaRoot_t           *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    tiIOCTLPayload_t     *agIOCTLPayload;

    if(status)
    {
        agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
        agIOCTLPayload->Status = (bit16)status;
    }

    TI_DBG1(("ostiSetNVMDIOCTLRsp: start, status = %d\n", status));
//    (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status;
    ostiFreeMemory(tiRoot,
                       tdsaAllShared->tdFWControlEx.buffer,
                       tdsaAllShared->tdFWControlEx.len);

    ostiIOCTLSetSignal(tiRoot,
                       tdsaAllShared->tdFWControlEx.param1,
                       tdsaAllShared->tdFWControlEx.param2,
                       NULL);
}
#ifdef SPC_ENABLE_PROFILE
/*****************************************************************************
*
* ostiFWProfileIOCTLRsp
*
* Purpose:  This routine is called for Fw Profile IOCTL reaponse has been received.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:          Pointer to driver instance
*   status:
*
* Return: none
*
*
*
*****************************************************************************/

osGLOBAL void ostiFWProfileIOCTLRsp(
                        tiRoot_t            *tiRoot,
                        bit32               status,
            bit32               len)
{
    tdsaRoot_t           *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    tdFWProfile_t        *fwProfile;

    TI_DBG1(("ostiFWProfileIOCTLRsp: start\n"));
    fwProfile = (tdFWProfile_t *)tdsaAllShared->tdFWProfileEx.tdFWProfile;
  //    (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status;
    if (status == AGSA_RC_SUCCESS)
    {
      if((fwProfile->cmd == STOP_TIMER_PROFILE) || (fwProfile->cmd == STOP_CODE_PROFILE))
        {
        osti_memcpy((void *)(fwProfile->buffer),
                  (void *)(tdsaAllShared->tdFWProfileEx.virtAddr),
                  len);

        ostiFreeMemory(tiRoot,
                         tdsaAllShared->tdFWProfileEx.buffer,
                         tdsaAllShared->tdFWProfileEx.len);
      }
    }
    fwProfile->status = status;
    fwProfile->len = len;
    ostiIOCTLSetSignal(tiRoot,
                       tdsaAllShared->tdFWProfileEx.param1,
                       tdsaAllShared->tdFWProfileEx.param2,
                       NULL);
}
#endif
/*****************************************************************************
*
* ostiGetNVMDIOCTLRsp
*
* Purpose:  This routine is called for Get NVMD IOCTL reaponse has been received.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:          Pointer to driver instance
*   payloadRsp:     Pointer to the FW download IOMB's payload.
*
* Return: none
*
*
*
*****************************************************************************/

osGLOBAL void ostiGetNVMDIOCTLRsp(
                        tiRoot_t            *tiRoot,
                        bit32               status
                        )
{
    tdsaRoot_t           *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    tiIOCTLPayload_t     *agIOCTLPayload;

    if(status)
    {
        agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
        agIOCTLPayload->Status = (bit16)status;
    }

    TI_DBG1(("ostiGetNVMDIOCTLRsp: start, status = %d\n", status));
    tdsaAllShared->NvmdResponseSet = 1;
   
    if(tdsaAllShared->tdFWControlEx.param1 != agNULL)
    {
    osti_memcpy((void *)(tdsaAllShared->tdFWControlEx.usrAddr),
                (void *)(tdsaAllShared->tdFWControlEx.virtAddr),
                tdsaAllShared->tdFWControlEx.len);

    ostiFreeMemory(tiRoot,
                   tdsaAllShared->tdFWControlEx.buffer,
                   tdsaAllShared->tdFWControlEx.len);

    ostiIOCTLSetSignal(tiRoot,
                       tdsaAllShared->tdFWControlEx.param1,
                       tdsaAllShared->tdFWControlEx.param2,
                       NULL);
    }
}


/*****************************************************************************
*
* ostiGetPhyProfileIOCTLRsp
*
* Purpose:  This routine is called for phy response has been received.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:          Pointer to driver instance
*   payloadRsp:     Pointer to the IOMB's payload.
*
* Return: none
*
*
*
*****************************************************************************/

osGLOBAL void ostiGetPhyProfileIOCTLRsp(
                        tiRoot_t            *tiRoot,
                        bit32               status
                        )
{
    tdsaRoot_t           *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    tiIOCTLPayload_t     *agIOCTLPayload;
    tdPhyCount_t     *PhyBlob = agNULL;
    if(status)
    {
      agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
      agIOCTLPayload->Status = (bit16)status;

      PhyBlob = (tdPhyCount_t*)&agIOCTLPayload->FunctionSpecificArea[0];
      if(PhyBlob)
      {
//        PhyBlob->Phy |= 0x800;
        if(PhyBlob->phyResetProblem == 0 )
        {
          PhyBlob->phyResetProblem = -1;
        }
        TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->Phy                   0x%x\n",PhyBlob->Phy));
        TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->BW_rx                 0x%x\n",PhyBlob->BW_rx));
        TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->BW_tx                 0x%x\n",PhyBlob->BW_tx));
        TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->InvalidDword          0x%x\n",PhyBlob->InvalidDword));
        TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->runningDisparityError 0x%x\n",PhyBlob->runningDisparityError));
        TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->codeViolation         0x%x\n",PhyBlob->codeViolation));
        TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->phyResetProblem       0x%x\n",PhyBlob->phyResetProblem));
        TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->inboundCRCError       0x%x\n",PhyBlob->inboundCRCError));

      }


    }

    TI_DBG1(("ostiGetPhyProfileIOCTLRsp: start, status = %d\n", status));
    TI_DBG1(("ostiGetPhyProfileIOCTLRsp: start, len = %d %p %p\n", tdsaAllShared->tdFWControlEx.len,tdsaAllShared->tdFWControlEx.usrAddr,tdsaAllShared->tdFWControlEx.virtAddr));

//    osti_memcpy((void *)(tdsaAllShared->tdFWControlEx.usrAddr),
//                (void *)(tdsaAllShared->tdFWControlEx.virtAddr),
//                 tdsaAllShared->tdFWControlEx.len);

    ostiFreeMemory(tiRoot,
                   tdsaAllShared->tdFWControlEx.buffer,
                   tdsaAllShared->tdFWControlEx.len);

    ostiIOCTLSetSignal(tiRoot,
                       tdsaAllShared->tdFWControlEx.param1,
                       tdsaAllShared->tdFWControlEx.param2,
                       NULL);
}


/*****************************************************************************
*
* ostiGenEventIOCTLRsp
*
* Purpose:  This routine is called when General Event happened while waiting for IOCTL response.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:          Pointer to driver instance
*   payloadRsp:     Pointer to the FW download IOMB's payload.
*
* Return: none
*
*
*
*****************************************************************************/

osGLOBAL void ostiGenEventIOCTLRsp(
                        tiRoot_t            *tiRoot,
                        bit32               status
                        )
{
    tdsaRoot_t           *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    tiIOCTLPayload_t     *agIOCTLPayload;

    TI_DBG1(("ostiGenEventIOCTLRsp: start\n"));

    if(tdsaAllShared->tdFWControlEx.inProgress)  /*Free only if our IOCTL is in progress*/
    {
      agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
      (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = IOCTL_ERR_STATUS_INTERNAL_ERROR;

      ostiFreeMemory(tiRoot,
                     tdsaAllShared->tdFWControlEx.buffer,
                     tdsaAllShared->tdFWControlEx.len);

      ostiIOCTLSetSignal(tiRoot,
                         tdsaAllShared->tdFWControlEx.param1,
                         tdsaAllShared->tdFWControlEx.param2,
                         NULL);
      tdsaAllShared->tdFWControlEx.inProgress = 0;
    }
#ifdef SPC_ENABLE_PROFILE
    if(tdsaAllShared->tdFWProfileEx.inProgress)
    {
      agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWProfileEx.payload);
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
      if(tdsaAllShared->tdFWProfileEx.virtAddr != NULL)  /*Free only if our IOCTL is in progress*/
      {
        ostiFreeMemory(tiRoot,
                       tdsaAllShared->tdFWProfileEx.buffer,
                       tdsaAllShared->tdFWProfileEx.len);
        tdsaAllShared->tdFWProfileEx.virtAddr = NULL;
      }
      ostiIOCTLSetSignal(tiRoot,
                         tdsaAllShared->tdFWProfileEx.param1,
                         tdsaAllShared->tdFWProfileEx.param2,
                         NULL);
      tdsaAllShared->tdFWProfileEx.inProgress = 0;

    }
#endif /*SPC_ENABLE_PROFILE*/

}

osGLOBAL void
ostiGetDeviceInfoIOCTLRsp(
                        tiRoot_t    *tiRoot,
                        bit32        status,
                        void        *param
                        )
{
    tdsaRoot_t             *tdsaRoot       = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t          *tdsaAllShared  = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    tiIOCTLPayload_t       *agIOCTLPayload = agNULL;
    tdDeviceInfoPayload_t  *pTDDeviceInfo  = agNULL;
    agsaDeviceInfo_t       *pSADeviceInfo  = agNULL;

    TI_DBG1(("ostiGetDeviceInfoIOCTLRsp: start\n"));

    agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
    pSADeviceInfo = (agsaDeviceInfo_t*)param;
    pTDDeviceInfo = (tdDeviceInfoPayload_t*)agIOCTLPayload->FunctionSpecificArea;

    if (pSADeviceInfo != agNULL)
    {
      /* fill the device information in IOCTL payload */
      osti_memcpy(&pTDDeviceInfo->devInfo.sasAddressHi, pSADeviceInfo->sasAddressHi, sizeof(bit32));
      osti_memcpy(&pTDDeviceInfo->devInfo.sasAddressLo, pSADeviceInfo->sasAddressLo, sizeof(bit32));

      pTDDeviceInfo->devInfo.sasAddressHi = DMA_BEBIT32_TO_BIT32(pTDDeviceInfo->devInfo.sasAddressHi);
      pTDDeviceInfo->devInfo.sasAddressLo = DMA_BEBIT32_TO_BIT32(pTDDeviceInfo->devInfo.sasAddressLo);

      pTDDeviceInfo->devInfo.deviceType = (pSADeviceInfo->devType_S_Rate & 0x30) >> 4;
      pTDDeviceInfo->devInfo.linkRate   = pSADeviceInfo->devType_S_Rate & 0x0F;

      agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
    }
    else
    {
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_INVALID_DEVICE;
    }

    if(tdsaAllShared->tdFWControlEx.inProgress)  /*Free only if our IOCTL is in progress*/
    {
      ostiIOCTLSetSignal(tiRoot,
                         tdsaAllShared->tdFWControlEx.param1,
                         tdsaAllShared->tdFWControlEx.param2,
                         NULL);
      tdsaAllShared->tdFWControlEx.inProgress = 0;
    }
}


#ifdef INITIATOR_DRIVER
osGLOBAL void
ostiGetIoErrorStatsIOCTLRsp(
                        tiRoot_t    *tiRoot,
                        bit32        status,
                        void        *param
                        )
{
    tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t               *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    itdsaIni_t                  *Initiator       = (itdsaIni_t *)tdsaAllShared->itdsaIni;
    tiIOCTLPayload_t            *agIOCTLPayload  = agNULL;
    tdIoErrorStatisticPayload_t *pIoErrorPayload = agNULL;
    agsaIOErrorEventStats_t     *pIoErrorCount   = agNULL;

    OS_ASSERT(sizeof(agsaIOErrorEventStats_t) == sizeof(tdIoErrorEventStatisticIOCTL_t), "agsaIOErrorEventStats_t tdIoErrorEventStatisticIOCTL_t\n");
    TI_DBG1(("ostiGetIoErrorStatsIOCTLRsp: start\n"));

    agIOCTLPayload  = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
    pIoErrorPayload = (tdIoErrorStatisticPayload_t*)agIOCTLPayload->FunctionSpecificArea;
    pIoErrorCount   = (agsaIOErrorEventStats_t*)param;

    osti_memcpy(&pIoErrorPayload->IoError, pIoErrorCount, sizeof(agsaIOErrorEventStats_t));
    /*copy SCSI status and sense key count from OS layer to TD layer*/
    osti_memcpy(&pIoErrorPayload->ScsiStatusCounter, &Initiator->ScsiStatusCounts, sizeof(tdSCSIStatusCount_t));
    osti_memcpy(&pIoErrorPayload->SenseKeyCounter, &Initiator->SenseKeyCounter, sizeof(tdSenseKeyCount_t));
    if (pIoErrorPayload->flag)
    {
      osti_memset(&Initiator->ScsiStatusCounts, 0,sizeof(tdSCSIStatusCount_t) );
      osti_memset(&Initiator->SenseKeyCounter, 0,sizeof(tdSenseKeyCount_t) );
    }

    agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
}
#endif /* INITIATOR_DRIVER */

osGLOBAL void
ostiGetIoEventStatsIOCTLRsp(
                        tiRoot_t    *tiRoot,
                        bit32        status,
                        void        *param
                        )
{
    tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t               *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    tiIOCTLPayload_t            *agIOCTLPayload  = agNULL;
    tdIoEventStatisticPayload_t *pIoEventPayload = agNULL;
    agsaIOErrorEventStats_t     *pIoEventCount   = agNULL;

    TI_DBG1(("ostiGetIoEventStatsIOCTLRsp: start\n"));

    agIOCTLPayload  = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
    pIoEventPayload = (tdIoEventStatisticPayload_t*)agIOCTLPayload->FunctionSpecificArea;
    pIoEventCount   = (agsaIOErrorEventStats_t*)param;

    osti_memcpy(&pIoEventPayload->IoEvent, pIoEventCount, sizeof(agsaIOErrorEventStats_t));

    agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
}

osGLOBAL void
ostiGetForensicDataIOCTLRsp(
                        tiRoot_t    *tiRoot,
                        bit32        status,
                        void        *param
                        )
{
  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t               *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  tiIOCTLPayload_t            *agIOCTLPayload  = agNULL;
  tdForensicDataPayload_t     *pForensicDataPayload = agNULL;
  agsaForensicData_t          *pForensicData   = agNULL;

  TI_DBG3(("ostiGetForensicDataIOCTLRsp: start, status = %d\n", status));

  agIOCTLPayload  = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
  pForensicDataPayload = (tdForensicDataPayload_t*)agIOCTLPayload->FunctionSpecificArea;
  pForensicData   = (agsaForensicData_t*)param;

  if (agNULL == agIOCTLPayload)
  {
    return;
  }

  if (FORENSIC_DATA_TYPE_CHECK_FATAL == pForensicData->DataType)
  {
    agIOCTLPayload->Status = (bit16)status;
    return;
  }

  if (status == AGSA_RC_SUCCESS)
  {
    switch (pForensicData->DataType)
    {
      case FORENSIC_DATA_TYPE_NON_FATAL:
      case FORENSIC_DATA_TYPE_FATAL:
           pForensicDataPayload->dataBuffer.directOffset = pForensicData->BufferType.dataBuf.directOffset;
           pForensicDataPayload->dataBuffer.readLen      = pForensicData->BufferType.dataBuf.readLen;
           break;
      case FORENSIC_DATA_TYPE_GSM_SPACE:
           pForensicDataPayload->gsmBuffer.directOffset  = pForensicData->BufferType.gsmBuf.directOffset;
	   pForensicDataPayload->gsmBuffer.readLen 	 = pForensicData->BufferType.gsmBuf.readLen;
           break;

      case FORENSIC_DATA_TYPE_QUEUE:
           break;

      default:
           TI_DBG1(("ostiGetForensicDataIOCTLRsp: forensic data type error %d\n", pForensicData->DataType));
           break;
    }
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
  }
  else if(status == IOCTL_ERROR_NO_FATAL_ERROR)
  {
    agIOCTLPayload->Status = (bit16)status;
  }
  else
  {
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
  }

  /*Free only if our IOCTL is in progress*/
  if(tdsaAllShared->tdFWControlEx.inProgress)
  {
    TI_DBG3(("ostiGetForensicDataIOCTLRsp: Waiting for the signal \n"));
    ostiIOCTLSetSignal(tiRoot,
          tdsaAllShared->tdFWControlEx.param1,
          tdsaAllShared->tdFWControlEx.param2,
          NULL);
    TI_DBG3(("ostiGetForensicDataIOCTLRsp: Signal wait completed \n"));
    tdsaAllShared->tdFWControlEx.inProgress = 0;
  }
}

/*****************************************************************************
*
* tdsaRegDumpGetIoctl
*
* Purpose:  This routine is called to get Register Dump information.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaRegDumpGetIoctl(
                tiRoot_t            *tiRoot,
                tiIOCTLPayload_t    *agIOCTLPayload,
                void                *agParam1,
                void                *agParam2,
                void                *agParam3
                )
{
    tdsaRoot_t    *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    agsaRoot_t    *agRoot = &(tdsaAllShared->agRootInt);
//    agsaControllerStatus_t RegDump;
    bit32               Offset = 0;
    bit32               RequestLength = 0;  /* user request on how much data to pass to application */
    agsaRegDumpInfo_t   regDumpInfo;
    void                *buffer = agNULL;
    void                *osMemHandle = agNULL;
    bit32               status = IOCTL_CALL_SUCCESS;
    bit32               CoreDumpLength = 16384; /* change it once data is available */
    bit32               EventLogOffset = 65536;

    ///saGetControllerStatus(agRoot, &RegDump);
    /* length of FSA as provided by application */
    RequestLength = agIOCTLPayload->Length;
///    FunctionSpecificOffset = 0; /* Offset into the FunctionSpecificArea of payload */
    /* offset into core dump that was passed from application */
    Offset = agIOCTLPayload->Reserved;

  if((CoreDumpLength <= Offset)&&
    (agIOCTLPayload->MinorFunction != IOCTL_MN_FW_GET_EVENT_FLASH_LOG1)&&
    (agIOCTLPayload->MinorFunction != IOCTL_MN_FW_GET_EVENT_FLASH_LOG2))
  {
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA;
      agIOCTLPayload->Length = 0;
      status=IOCTL_CALL_SUCCESS;
      return status;
    }
    regDumpInfo.regDumpOffset = Offset;
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
    /* dump either aap1 or iop registers */
    switch(agIOCTLPayload->MinorFunction){

    /*Coredump*/
    case IOCTL_MN_FW_GET_CORE_DUMP_AAP1:
            //CoreDumpBAROffset = RegDump.fatalErrorInfo.regDumpOffset0;    /* get this from mpi config table */
            //CoreDumpLength = RegDump.fatalErrorInfo.regDumpLen0;
            /*changes for added Call back*/
            tdsaAllShared->tdFWControlEx.param1 = agParam1;
            tdsaAllShared->tdFWControlEx.param2 = agParam2;
            regDumpInfo.regDumpSrc = 0;
            regDumpInfo.regDumpNum = 0;
            regDumpInfo.directLen = RequestLength;
            regDumpInfo.directData = &agIOCTLPayload->FunctionSpecificArea[0];
            /*changes for added Call back*/
            //status = IOCTL_CALL_SUCCESS;
            tdsaAllShared->tdFWControlEx.inProgress = 1;
            status = IOCTL_CALL_PENDING;
            break;
    case IOCTL_MN_FW_GET_CORE_DUMP_IOP:
        //CoreDumpBAROffset = RegDump.fatalErrorInfo.regDumpOffset1;    /* get this from mpi config table */
        //CoreDumpLength = RegDump.fatalErrorInfo.regDumpLen1;
        /*changes for added Call back*/
        tdsaAllShared->tdFWControlEx.param1 = agParam1;
        tdsaAllShared->tdFWControlEx.param2 = agParam2;
        regDumpInfo.regDumpSrc = 0;
        regDumpInfo.regDumpNum = 1;
        regDumpInfo.directLen = RequestLength;
        regDumpInfo.directData = &agIOCTLPayload->FunctionSpecificArea[0];
        /*changes for added Call back*/
        //status = IOCTL_CALL_SUCCESS;
        tdsaAllShared->tdFWControlEx.inProgress = 1;
        status = IOCTL_CALL_PENDING;
        break;
    case IOCTL_MN_FW_GET_CORE_DUMP_FLASH_AAP1:
        regDumpInfo.regDumpSrc = 1;
        regDumpInfo.regDumpNum = 0;
        if(RequestLength != 0)
        {
            if(ostiAllocMemory( tiRoot,
                    &osMemHandle,
                    (void **)&buffer,
                    &(regDumpInfo.indirectAddrUpper32),
                    &(regDumpInfo.indirectAddrLower32),
                    8,
                    RequestLength,
                    agFALSE))
                return IOCTL_CALL_FAIL;
        }
        osti_memset((void *)buffer, 0, RequestLength);
        regDumpInfo.indirectLen = RequestLength;

        // use FW control place in shared structure to keep the neccesary information
        tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
        tdsaAllShared->tdFWControlEx.virtAddr = buffer;
        tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
        tdsaAllShared->tdFWControlEx.len = RequestLength;
        tdsaAllShared->tdFWControlEx.param1 = agParam1;
        tdsaAllShared->tdFWControlEx.param2 = agParam2;
        tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
        tdsaAllShared->tdFWControlEx.inProgress = 1;
        status = IOCTL_CALL_PENDING;
        break;
    case IOCTL_MN_FW_GET_CORE_DUMP_FLASH_IOP:
        regDumpInfo.regDumpSrc = 1;
        regDumpInfo.regDumpNum = 1;
        if(RequestLength != 0)
        {
            if(ostiAllocMemory( tiRoot,
                    &osMemHandle,
                    (void **)&buffer,
                    &(regDumpInfo.indirectAddrUpper32),
                    &(regDumpInfo.indirectAddrLower32),
                    8,
                    RequestLength,
                    agFALSE))
                return IOCTL_CALL_FAIL;
        }
        osti_memset((void *)buffer, 0, RequestLength);
        regDumpInfo.indirectLen = RequestLength;

        // use FW control place in shared structure to keep the neccesary information
        tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
        tdsaAllShared->tdFWControlEx.virtAddr = buffer;
        tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
        tdsaAllShared->tdFWControlEx.len = RequestLength;
        tdsaAllShared->tdFWControlEx.param1 = agParam1;
        tdsaAllShared->tdFWControlEx.param2 = agParam2;
        tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
        tdsaAllShared->tdFWControlEx.inProgress = 1;
        status = IOCTL_CALL_PENDING;
        break;
    /*EventLog from Flash*/
    case IOCTL_MN_FW_GET_EVENT_FLASH_LOG1:      //aap1 Eventlog
      if(CoreDumpLength + EventLogOffset <= Offset)
      {
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA;
        agIOCTLPayload->Length = 0;
        status=IOCTL_CALL_SUCCESS;
        return status;
      }
      regDumpInfo.regDumpSrc = 1;
      regDumpInfo.regDumpNum = 0;
      if(RequestLength != 0)
      {
          if(ostiAllocMemory( tiRoot,
                  &osMemHandle,
                  (void **)&buffer,
                  &(regDumpInfo.indirectAddrUpper32),
                  &(regDumpInfo.indirectAddrLower32),
                  8,
                  RequestLength,
                  agFALSE))
              return IOCTL_CALL_FAIL;
      }
      osti_memset((void *)buffer, 0, RequestLength);
      regDumpInfo.indirectLen = RequestLength;

      // use FW control place in shared structure to keep the neccesary information
      tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
      tdsaAllShared->tdFWControlEx.virtAddr = buffer;
      tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
      tdsaAllShared->tdFWControlEx.len = RequestLength;
      tdsaAllShared->tdFWControlEx.param1 = agParam1;
      tdsaAllShared->tdFWControlEx.param2 = agParam2;
      tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
      tdsaAllShared->tdFWControlEx.inProgress = 1;
      status = IOCTL_CALL_PENDING;
      break;
    case IOCTL_MN_FW_GET_EVENT_FLASH_LOG2:      //iop Eventlog
      if(CoreDumpLength + EventLogOffset <= Offset)
      {
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA;
        agIOCTLPayload->Length = 0;
        status=IOCTL_CALL_SUCCESS;
        return status;
      }
      regDumpInfo.regDumpSrc = 1;
      regDumpInfo.regDumpNum = 1;
      if(RequestLength != 0)
      {
          if(ostiAllocMemory( tiRoot,
                  &osMemHandle,
                  (void **)&buffer,
                  &(regDumpInfo.indirectAddrUpper32),
                  &(regDumpInfo.indirectAddrLower32),
                  8,
                  RequestLength,
                  agFALSE))
              return IOCTL_CALL_FAIL;
      }
      osti_memset((void *)buffer, 0, RequestLength);
      regDumpInfo.indirectLen = RequestLength;

      // use FW control place in shared structure to keep the neccesary information
      tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
      tdsaAllShared->tdFWControlEx.virtAddr = buffer;
      tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
      tdsaAllShared->tdFWControlEx.len = RequestLength;
      tdsaAllShared->tdFWControlEx.param1 = agParam1;
      tdsaAllShared->tdFWControlEx.param2 = agParam2;
      tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
      tdsaAllShared->tdFWControlEx.inProgress = 1;
      status = IOCTL_CALL_PENDING;
      break;
  default:
      status = IOCTL_CALL_INVALID_CODE;
      TI_DBG1(("tiCOMMgntIOCTL: ERROR: Wrong IOCTL code %d\n", agIOCTLPayload->MinorFunction));
      break;
    }
    if(saGetRegisterDump(agRoot, agNULL, 0, &regDumpInfo) != AGSA_RC_SUCCESS)
    {
        status = IOCTL_CALL_FAIL;
        agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
    }

    return status;
}

osGLOBAL void
ostiCOMMgntVPDSetIOCTLRsp(
                          tiRoot_t            *tiRoot,
                          bit32               status
                          )
{
    tdsaRoot_t    *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
//    agsaRoot_t    *agRoot = &(tdsaAllShared->agRootInt);

    TI_DBG1(("ostiCOMMgntVPDSetIOCTLRsp: start\n"));
    (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status;

    ostiFreeMemory(tiRoot,
                   tdsaAllShared->tdFWControlEx.buffer,
                   tdsaAllShared->tdFWControlEx.len);

    ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1,
                               tdsaAllShared->tdFWControlEx.param2,
                               NULL);
}

/*****************************************************************************
*
* tdsaNVMDSetIoctl
*
* Purpose:  This routine is called to set Config. SEEPROM information.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaNVMDSetIoctl(
                tiRoot_t            *tiRoot,
                tiIOCTLPayload_t    *agIOCTLPayload,
                void                *agParam1,
                void                *agParam2,
                void                *agParam3
                )
{
  bit32                  RequestLength = 0;
  bit32                  bufAddrUpper = 0;
  bit32                  bufAddrLower = 0;
  tdsaRoot_t             *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t          *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t             *agRoot = &(tdsaAllShared->agRootInt);
  void                   *buffer = agNULL;
  void                   *osMemHandle = agNULL;
  bit32                  status = IOCTL_CALL_SUCCESS;
  agsaNVMDData_t         nvmdInfo;


  TI_DBG2(("tdsaNVMDSetIoctl: start\n"));

  RequestLength = agIOCTLPayload->Length;

  osti_memset(&nvmdInfo, 0, sizeof(agsaNVMDData_t));

  switch(agIOCTLPayload->MinorFunction)
  {
    case IOCTL_MN_NVMD_SET_CONFIG:

      //nvmdInfo.NVMDevice = 1;
      nvmdInfo.NVMDevice = *((bit8*)agParam3);
      nvmdInfo.signature = 0xFEDCBA98;
      nvmdInfo.dataOffsetAddress = agIOCTLPayload->Reserved;
      nvmdInfo.indirectPayload = 1;
      nvmdInfo.indirectLen = RequestLength;

      if (nvmdInfo.NVMDevice == 0) {
        nvmdInfo.TWIDeviceAddress = 0xa0;
        nvmdInfo.TWIBusNumber = 0;
        nvmdInfo.TWIDevicePageSize = 0;
        nvmdInfo.TWIDeviceAddressSize = 1;
      }

      if(RequestLength != 0)
      {
        if(ostiAllocMemory( tiRoot,
            &osMemHandle,
            (void **)&buffer,
            &bufAddrUpper,
            &bufAddrLower,
            8,
            RequestLength,
            agFALSE))
          return IOCTL_CALL_FAIL;
      }
      else
      {
        return IOCTL_CALL_FAIL;
      }

      osti_memset((void *)buffer, 0, RequestLength);

      osti_memcpy((void *)buffer,
            agIOCTLPayload->FunctionSpecificArea,
            RequestLength);

      nvmdInfo.indirectAddrLower32 = bufAddrLower;
      nvmdInfo.indirectAddrUpper32 = bufAddrUpper;
      // use FW control place in shared structure to keep the neccesary information
      tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
      tdsaAllShared->tdFWControlEx.virtAddr = buffer;
      tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
      tdsaAllShared->tdFWControlEx.len = RequestLength;
      tdsaAllShared->tdFWControlEx.param1 = agParam1;
      tdsaAllShared->tdFWControlEx.param2 = agParam2;
      tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
      tdsaAllShared->tdFWControlEx.inProgress = 1;
      status = IOCTL_CALL_PENDING;
      break;
    default:
        status = IOCTL_CALL_INVALID_CODE;
        TI_DBG1(("tdsaNVMDSetIoctl: ERROR: Wrong IOCTL code %d\n", agIOCTLPayload->MinorFunction));
        break;
  }

  if(saSetNVMDCommand(agRoot, agNULL, 0, &nvmdInfo) != AGSA_RC_SUCCESS)
  {
      status = IOCTL_CALL_FAIL;
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
  }

  return status;

}

/*****************************************************************************
*
* tdsaNVMDGetIoctl
*
* Purpose:  This routine is called to get Config. SEEPROM information.
*           This function is used for both target and initiator.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaNVMDGetIoctl(
                tiRoot_t            *tiRoot,
                tiIOCTLPayload_t    *agIOCTLPayload,
                void                *agParam1,
                void                *agParam2,
                void                *agParam3
                )
{
  tdsaRoot_t      *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t   *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t      *agRoot = &(tdsaAllShared->agRootInt);
  void            *buffer = agNULL;
  void            *osMemHandle = agNULL;
  bit32           status = IOCTL_CALL_SUCCESS;
  agsaNVMDData_t  nvmdInfo;
  bit32           Offset = 0;
  bit32           RequestLength = 0;
  bit32		  ostiMemoryStatus = 0;
  bit32		  i,j;
  bit8*		  seepromBuffer;
  bit8*		  phySettingsBuffer;


  TI_DBG2(("tdsaNVMDGetIoctl: start\n"));

  RequestLength = agIOCTLPayload->Length;
  Offset = agIOCTLPayload->Reserved;

  osti_memset(&nvmdInfo, 0, sizeof(agsaNVMDData_t));
  /* This condition is not valid for direct read so commenting */
  /*if(!tiIS_SPC(agRoot)) {
     if( RequestLength <= Offset ) //4096-max seeprom size
     {
    	agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA;
    	agIOCTLPayload->Length = 0;
    	status=IOCTL_CALL_SUCCESS;
    	return status;
     }
  }*/

  agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;

  switch(agIOCTLPayload->MinorFunction)
  {
    case IOCTL_MN_NVMD_GET_CONFIG:

   //   nvmdInfo.NVMDevice = 1;
      nvmdInfo.NVMDevice = *((bit8*)agParam3);
      nvmdInfo.signature = 0xFEDCBA98;
      nvmdInfo.dataOffsetAddress = Offset;
      nvmdInfo.indirectPayload = 1;
      nvmdInfo.indirectLen = RequestLength;

      if (nvmdInfo.NVMDevice == 0) {
        nvmdInfo.TWIDeviceAddress = 0xa0;
        nvmdInfo.TWIBusNumber = 0;
        nvmdInfo.TWIDevicePageSize = 0;
        nvmdInfo.TWIDeviceAddressSize = 1;
      }

      if(RequestLength != 0)
      {
        ostiMemoryStatus = ostiAllocMemory( tiRoot,
            &osMemHandle,
            (void **)&buffer,
            &(nvmdInfo.indirectAddrUpper32),
            &(nvmdInfo.indirectAddrLower32),
            8,
            RequestLength,
            agFALSE);
	if((ostiMemoryStatus != tiSuccess) && (buffer == agNULL))
        return IOCTL_CALL_FAIL;
     }
      else
      {
        return IOCTL_CALL_FAIL;
      }
      osti_memset((void *)buffer, 0, RequestLength);

      // use FW control place in shared structure to keep the neccesary information
      tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
      tdsaAllShared->tdFWControlEx.virtAddr = buffer;
      tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
      tdsaAllShared->tdFWControlEx.len = RequestLength;
      tdsaAllShared->tdFWControlEx.param1 = agParam1;
      tdsaAllShared->tdFWControlEx.param2 = agParam2;
      tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
      tdsaAllShared->tdFWControlEx.inProgress = 1;
      status = IOCTL_CALL_PENDING;
      break;
      default:
      status = IOCTL_CALL_INVALID_CODE;
      TI_DBG1(("tiCOMMgntIOCTL: ERROR: Wrong IOCTL code %d\n", agIOCTLPayload->MinorFunction));
      break;
  }
  tdsaAllShared->NvmdResponseSet = 0;

  if(saGetNVMDCommand(agRoot, agNULL, 0, &nvmdInfo) != AGSA_RC_SUCCESS)
  {
    status = IOCTL_CALL_FAIL;
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
    return status;
  }
  /* Copy the SAS address */
  if(agParam1 == agNULL)
 
  {
     while(!tdsaAllShared->NvmdResponseSet)
     {
   //	tiCOMDelayedInterruptHandler(tiRoot, 0, 1, tiNonInterruptContext);
     }
     if(nvmdInfo.NVMDevice == 4 || nvmdInfo.NVMDevice == 1)
     {
	seepromBuffer = buffer;
	/*Get Initiator SAS address*/

	if(tiIS_SPC(agRoot))
	{
	   for(j=0,i=ADAPTER_WWN_SPC_START_OFFSET; i<= ADAPTER_WWN_SPC_END_OFFSET; i++,j++)
	  agIOCTLPayload->FunctionSpecificArea[j] = seepromBuffer[i];
        }
 	else
	{
	  for(j=0,i=ADAPTER_WWN_START_OFFSET; i<= ADAPTER_WWN_END_OFFSET; i++,j++)
	  agIOCTLPayload->FunctionSpecificArea[j] = seepromBuffer[i];
	}
    }
    /* Copy the Phy settings */
    else if(nvmdInfo.NVMDevice == 6)
    {
      phySettingsBuffer = buffer;
      for(i=0; i<PHY_SETTINGS_LEN; i++)
	agIOCTLPayload->FunctionSpecificArea[i] = phySettingsBuffer[i];
    }
    tdsaAllShared->NvmdResponseSet = 0;
    ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.len);

  }
  return status;

}

/*****************************************************************************
*
* tdsaDeviceInfoGetIoctl
*
* Purpose:  This routine is called to get the specified device information.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaDeviceInfoGetIoctl(
                tiRoot_t            *tiRoot,
                tiIOCTLPayload_t    *agIOCTLPayload,
                void                *agParam1,
                void                *agParam2,
                void                *agParam3
                )
{
  tdsaDeviceData_t       *oneDeviceData = agNULL;
  tiDeviceHandle_t       *tiDeviceHandle = agNULL;
  tdDeviceInfoPayload_t  *pDeviceInfo = agNULL;
  /*agsaDevHandle_t  *agDevHandle = agNULL;*/
  bit32            status = IOCTL_CALL_SUCCESS;

  pDeviceInfo = (tdDeviceInfoPayload_t*)agIOCTLPayload->FunctionSpecificArea;

  TI_DBG3(("tdsaDeviceInfoGetIoctl: %d:%3d:%d %p %p %p\n",
                                     (bit8)pDeviceInfo->PathId,
                                     (bit8)pDeviceInfo->TargetId,
                                     (bit8)pDeviceInfo->Lun,
                                      agParam1,
                                      agParam2,
                                      agParam3));

  tiDeviceHandle = ostiMapToDevHandle(tiRoot,
                                     (bit8)pDeviceInfo->PathId,
                                     (bit8)pDeviceInfo->TargetId,
                                     (bit8)pDeviceInfo->Lun
                                     );

  if (tiDeviceHandle == agNULL)
  {
    TI_DBG1(("tdsaDeviceInfoGetIoctl: tiDeviceHandle is NULL !!!! SCSI address = %d:%3d:%d\n",
              pDeviceInfo->PathId, pDeviceInfo->TargetId, pDeviceInfo->Lun));
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_INVALID_DEVICE;
    status = IOCTL_CALL_FAIL;
    return status;
  }

  oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
  if(oneDeviceData == agNULL)
  {
    TI_DBG1(("tdsaDeviceInfoGetIoctl: tiDeviceHandle=%p DeviceData is NULL!!! SCSI address = %d:%3d:%d\n",
             tiDeviceHandle, pDeviceInfo->PathId, pDeviceInfo->TargetId, pDeviceInfo->Lun));
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_INVALID_DEVICE;
    status = IOCTL_CALL_FAIL;
    return status;
  }

  /* for hotplug */
  if (oneDeviceData->valid != agTRUE || oneDeviceData->registered != agTRUE ||
      oneDeviceData->tdPortContext == agNULL )
  {
    TI_DBG1(("tdsaDeviceInfoGetIoctl: tiDeviceHandle=%p did %d DeviceData was removed!!! SCSI address = %d:%3d:%d\n",
             tiDeviceHandle, oneDeviceData->id, pDeviceInfo->PathId, pDeviceInfo->TargetId, pDeviceInfo->Lun));
    agIOCTLPayload->Status = IOCTL_ERR_STATUS_INVALID_DEVICE;
    status = IOCTL_CALL_FAIL;
    return status;
  }

  /* fill the device information in IOCTL payload */
  pDeviceInfo->devInfo.phyId = oneDeviceData->phyID;
  osti_memcpy(&pDeviceInfo->devInfo.sasAddressHi, oneDeviceData->agDeviceInfo.sasAddressHi, sizeof(bit32));
  osti_memcpy(&pDeviceInfo->devInfo.sasAddressLo, oneDeviceData->agDeviceInfo.sasAddressLo, sizeof(bit32));

  pDeviceInfo->devInfo.sasAddressHi = DMA_BEBIT32_TO_BIT32(pDeviceInfo->devInfo.sasAddressHi);
  pDeviceInfo->devInfo.sasAddressLo = DMA_BEBIT32_TO_BIT32(pDeviceInfo->devInfo.sasAddressLo);

  pDeviceInfo->devInfo.deviceType = (oneDeviceData->agDeviceInfo.devType_S_Rate & 0x30) >> 4;
  pDeviceInfo->devInfo.linkRate   = oneDeviceData->agDeviceInfo.devType_S_Rate & 0x0F;

  agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;

  TI_DBG3(("tdsaDeviceInfoGetIoctl:IOCTL_CALL_SUCCESS\n"));

  /*saGetDeviceInfo(agRoot, agNULL, 0, 0, agDevHandle);*/

  status = IOCTL_CALL_SUCCESS;

  return status;
}
/*****************************************************************************
*
* tdsaIoErrorStatisticGetIoctl
*
* Purpose:  This routine is called to get the IO error statistic.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaIoErrorStatisticGetIoctl(
                 tiRoot_t            *tiRoot,
                 tiIOCTLPayload_t    *agIOCTLPayload,
                 void                *agParam1,
                 void                *agParam2,
                 void                *agParam3
                 )
{
  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t               *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t                  *agRoot          = &(tdsaAllShared->agRootInt);
  tdIoErrorStatisticPayload_t *pIoErrorPayload = agNULL;
  bit32                        status = IOCTL_CALL_SUCCESS;

  pIoErrorPayload = (tdIoErrorStatisticPayload_t*)agIOCTLPayload->FunctionSpecificArea;

  tdsaAllShared->tdFWControlEx.buffer = agNULL;
  tdsaAllShared->tdFWControlEx.virtAddr = agNULL;
  tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
  tdsaAllShared->tdFWControlEx.len = 0;
  tdsaAllShared->tdFWControlEx.param1 = agParam1;
  tdsaAllShared->tdFWControlEx.param2 = agParam2;
  tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
  tdsaAllShared->tdFWControlEx.inProgress = 0;

  saGetIOErrorStats(agRoot, agNULL, pIoErrorPayload->flag);

  return status;
}

/*****************************************************************************
*
* tdsaIoEventStatisticGetIoctl
*
* Purpose:  This routine is called to get the IO event statistic.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaIoEventStatisticGetIoctl(
                 tiRoot_t            *tiRoot,
                 tiIOCTLPayload_t    *agIOCTLPayload,
                 void                *agParam1,
                 void                *agParam2,
                 void                *agParam3
                 )
{
  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t               *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t                  *agRoot          = &(tdsaAllShared->agRootInt);
  tdIoEventStatisticPayload_t *pIoEventPayload = agNULL;
  bit32                        status = IOCTL_CALL_SUCCESS;

  pIoEventPayload = (tdIoEventStatisticPayload_t*)agIOCTLPayload->FunctionSpecificArea;

  tdsaAllShared->tdFWControlEx.buffer = agNULL;
  tdsaAllShared->tdFWControlEx.virtAddr = agNULL;
  tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
  tdsaAllShared->tdFWControlEx.len = 0;
  tdsaAllShared->tdFWControlEx.param1 = agParam1;
  tdsaAllShared->tdFWControlEx.param2 = agParam2;
  tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
  tdsaAllShared->tdFWControlEx.inProgress = 0;

  saGetIOEventStats(agRoot, agNULL, pIoEventPayload->flag);

  return status;
}

/*****************************************************************************
*
* tdsaRegisterIoctl
*
* Purpose:  This routine is called to get Forensic Data.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaRegisterIoctl(
                 tiRoot_t            *tiRoot,
                 tiIOCTLPayload_t    *agIOCTLPayload,
                 void                *agParam1,
                 void                *agParam2,
                 void                *agParam3
                 )
{
  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t               *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
//  agsaRoot_t                  *agRoot          = &(tdsaAllShared->agRootInt);
  tdRegisterPayload_t         *pRegisterPayload = agNULL;
  bit32                        status = IOCTL_CALL_SUCCESS;

  pRegisterPayload = (tdRegisterPayload_t*)agIOCTLPayload->FunctionSpecificArea;

  tdsaAllShared->tdFWControlEx.buffer = agNULL;
  tdsaAllShared->tdFWControlEx.virtAddr = agNULL;
  tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
  tdsaAllShared->tdFWControlEx.len = 0;
  tdsaAllShared->tdFWControlEx.param1 = agParam1;
  tdsaAllShared->tdFWControlEx.param2 = agParam2;
  tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
  tdsaAllShared->tdFWControlEx.inProgress = 0;

  TI_DBG1(("tdsaRegisterIoctl: Flag %d RegAddr 0x%x RegValue 0x%x\n",
            pRegisterPayload->flag, pRegisterPayload->RegAddr, pRegisterPayload->RegValue));

  if (pRegisterPayload->flag)
  {
    /* set register */
    ostiChipWriteBit32Ext(tiRoot, 0, pRegisterPayload->RegAddr, pRegisterPayload->RegValue);
  }
  else
  {
    /* get register */
    pRegisterPayload->RegValue = ostiChipReadBit32Ext(tiRoot, 0, pRegisterPayload->RegAddr);
  }
  agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
  return status;
}

osGLOBAL bit32
tdsaGetPhyGeneralStatusIoctl(
				tiRoot_t			      *tiRoot,
				agsaPhyGeneralState_t     *PhyData
				)
{
  tdsaRoot_t				*tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t 			*tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t				*agRoot = &(tdsaAllShared->agRootNonInt);
//  agsaLLRoot_t	            *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
//  bit8                      totalValidPhys;
  bit32 					 status = AGSA_RC_SUCCESS;
  bit32                      i = 0;
  agsaControllerInfo_t ControllerInfo;
  saGetControllerInfo(agRoot,&ControllerInfo);

  TI_DBG3(("tdsaGetPhyGeneralStatusIoctl: start\n"));
  do
  {
    if(tIsSPC(agRoot)||tIsSPCHIL(agRoot))
    {
  	    status = IOCTL_ERR_STATUS_NOT_SUPPORTED;
		break;
    }
	
    PhyData->Reserved1 = ControllerInfo.phyCount;
    for(i=0;i<PhyData->Reserved1;i++)
    {
      status = saGetPhyProfile( agRoot,agNULL,tdsaRotateQnumber(tiRoot, agNULL), AGSA_SAS_PHY_GENERAL_STATUS_PAGE,i);
      if(status == AGSA_RC_FAILURE)
	  {
	    break;
	  }
    }
  }while(0);
  TI_DBG3(("tdsaGetPhyGeneralStatusIoctl: End\n"));
  return status;
}
/*****************************************************************************
*
* ostiGetPhyGeneralStatusRsp
*
* Purpose:  This routine is called when a PhyStatus IOCTL response is received.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agsaSASPhyGeneralStatusPage_t:   Status of the phy.
*   bit32:          phyID
*
* Return: none
*
*
*****************************************************************************/
osGLOBAL void ostiGetPhyGeneralStatusRsp(
                            tiRoot_t                      *tiRoot,
                        	agsaSASPhyGeneralStatusPage_t *GenStatus,
                        	bit32                          phyID
                            )
{

  tdsaRoot_t               *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t            *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  tiIOCTLPayload_t         *agIoctlPayload = agNULL;
  agsaPhyGeneralState_t    *pSetPhyStatusRes = agNULL;

                   
  TI_DBG1(("ostiGetPhyGeneralStatusRsp: start\n"));

  if (tdsaAllShared->tdFWControlEx.inProgress) 
  {
      agIoctlPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
      if ((agIoctlPayload) && (PMC_IOCTL_SIGNATURE == agIoctlPayload->Signature)&& 
	  	                 (IOCTL_MJ_PHY_GENERAL_STATUS == agIoctlPayload->MajorFunction))
      {
        pSetPhyStatusRes = (agsaPhyGeneralState_t*) &agIoctlPayload->FunctionSpecificArea[0];
		osti_memcpy(&pSetPhyStatusRes->PhyGenData[phyID], GenStatus, sizeof(agsaSASPhyGeneralStatusPage_t));
		pSetPhyStatusRes->Reserved2++;
        if(pSetPhyStatusRes->Reserved1 == pSetPhyStatusRes->Reserved2)
        {
  		  tdsaAllShared->tdFWControlEx.payload = NULL; 
          ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1,
                          tdsaAllShared->tdFWControlEx.param2, agNULL);
	  tdsaAllShared->tdFWControlEx.inProgress = 0;
          agIoctlPayload->Status = IOCTL_ERR_STATUS_OK;
		
        }
  	  } 
  }

  TI_DBG1(("ostiGetPhyGeneralStatusRsp: end\n"));
}


osGLOBAL bit32
tdsaPhyProfileIoctl(
                 tiRoot_t            *tiRoot,
                 tiIOCTLPayload_t    *agIOCTLPayload,
                 void                *agParam1,
                 void                *agParam2,
                 void                *agParam3
                 )
{
  tdsaRoot_t       *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t    *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t       *agRoot          = &(tdsaAllShared->agRootInt);
  void             *buffer = agNULL;
  void             *osMemHandle = agNULL;
  bit32            status = IOCTL_CALL_SUCCESS;
  bit32            retcode = AGSA_RC_FAILURE;
  bit32            RequestLength= agIOCTLPayload->Length;
  bit32 	   bufAddrUpper = 0;
  bit32 	   bufAddrLower = 0;

  tdPhyCount_t     *PhyBlob = (tdPhyCount_t*)&agIOCTLPayload->FunctionSpecificArea[0];


  if(ostiAllocMemory( tiRoot,
      &osMemHandle,
      (void **)&buffer,
      &bufAddrUpper,
      &bufAddrLower,
      RequestLength,
      RequestLength,
      agTRUE))
    return IOCTL_CALL_FAIL;


  tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
  tdsaAllShared->tdFWControlEx.virtAddr = buffer;
  tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
  tdsaAllShared->tdFWControlEx.len = 32;
  tdsaAllShared->tdFWControlEx.param1 = agParam1;
  tdsaAllShared->tdFWControlEx.param2 = agParam2;
  tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
  tdsaAllShared->tdFWControlEx.inProgress = 1;

  TI_DBG1(("tdsaPhyProfileIoctl: MinorFunction %d\n",agIOCTLPayload->MinorFunction));
//  PhyBlob->Phy |= 0x100;

  if( tiIS_SPC(agRoot) )
  {
    TI_DBG1(("tdsaPhyProfileIoctl: SPC operation 0x%x PHY %d\n",agIOCTLPayload->MinorFunction,PhyBlob->Phy));
    retcode = saLocalPhyControl(agRoot,agNULL,0 ,PhyBlob->Phy ,agIOCTLPayload->MinorFunction , agNULL);
    if(retcode ==  AGSA_RC_SUCCESS)
    {
      status = IOCTL_CALL_PENDING;
    }
  }
  else
  {
    TI_DBG1(("tdsaPhyProfileIoctl: SPCv operation 0x%x PHY %d\n",agIOCTLPayload->MinorFunction,PhyBlob->Phy));
    retcode = saGetPhyProfile( agRoot,agNULL,0,agIOCTLPayload->MinorFunction , PhyBlob->Phy);

    if(retcode ==  AGSA_RC_SUCCESS)
    {
      status = IOCTL_CALL_PENDING;
    }

  }

  TI_DBG2(("tdsaPhyProfileIoctl: after\n"));


  return status;
}

/*****************************************************************************
*
* tdsaForensicDataGetIoctl
*
* Purpose:  This routine is called to get Forensic Data.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaForensicDataGetIoctl(
                 tiRoot_t            *tiRoot,
                 tiIOCTLPayload_t    *agIOCTLPayload,
                 void                *agParam1,
                 void                *agParam2,
                 void                *agParam3
                 )
{
  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t               *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t                  *agRoot          = &(tdsaAllShared->agRootInt);
  tdForensicDataPayload_t     *pForensicDataPayload = agNULL;
  agsaForensicData_t           ForensicData;
  bit32                        status = IOCTL_CALL_SUCCESS;

  pForensicDataPayload = (tdForensicDataPayload_t*)agIOCTLPayload->FunctionSpecificArea;

  tdsaAllShared->tdFWControlEx.buffer = agNULL;
  tdsaAllShared->tdFWControlEx.virtAddr = agNULL;
  tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
  tdsaAllShared->tdFWControlEx.len = 0;
  tdsaAllShared->tdFWControlEx.param1 = agParam1;
  tdsaAllShared->tdFWControlEx.param2 = agParam2;
  tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
  tdsaAllShared->tdFWControlEx.inProgress = 0;

  osti_memset(&ForensicData, 0, sizeof(agsaForensicData_t));

  ForensicData.DataType = pForensicDataPayload->DataType;

  switch (ForensicData.DataType)
  {
    case FORENSIC_DATA_TYPE_NON_FATAL:
    case FORENSIC_DATA_TYPE_FATAL:
         ForensicData.BufferType.dataBuf.directLen = pForensicDataPayload->dataBuffer.directLen;
         ForensicData.BufferType.dataBuf.directOffset = pForensicDataPayload->dataBuffer.directOffset;
         ForensicData.BufferType.dataBuf.readLen = pForensicDataPayload->dataBuffer.readLen;
         ForensicData.BufferType.dataBuf.directData = (void*)pForensicDataPayload->dataBuffer.directData;         
		 break;
    case FORENSIC_DATA_TYPE_GSM_SPACE:
         ForensicData.BufferType.gsmBuf.directLen = pForensicDataPayload->gsmBuffer.directLen;
         ForensicData.BufferType.gsmBuf.directOffset = pForensicDataPayload->gsmBuffer.directOffset;
         ForensicData.BufferType.dataBuf.readLen      = pForensicDataPayload->gsmBuffer.readLen;
         ForensicData.BufferType.gsmBuf.directData = (void*)pForensicDataPayload->gsmBuffer.directData;
         break;

    case FORENSIC_DATA_TYPE_IB_QUEUE:
         ForensicData.BufferType.queueBuf.directLen = pForensicDataPayload->queueBuffer.directLen;
         //ForensicData.BufferType.queueBuf.queueType = pForensicDataPayload->queueBuffer.queueType;
         ForensicData.BufferType.queueBuf.queueType = FORENSIC_DATA_TYPE_IB_QUEUE;
         ForensicData.BufferType.queueBuf.queueIndex = pForensicDataPayload->queueBuffer.queueIndex;
         ForensicData.BufferType.queueBuf.directData = (void*)pForensicDataPayload->queueBuffer.directData;
         break;
    case FORENSIC_DATA_TYPE_OB_QUEUE:
         ForensicData.BufferType.queueBuf.directLen = pForensicDataPayload->queueBuffer.directLen;
         ForensicData.BufferType.queueBuf.queueType = FORENSIC_DATA_TYPE_OB_QUEUE;
         ForensicData.BufferType.queueBuf.queueIndex = pForensicDataPayload->queueBuffer.queueIndex;
         ForensicData.BufferType.queueBuf.directData = (void*)pForensicDataPayload->queueBuffer.directData;
         break;

    default:
         TI_DBG1(("tdsaGetForensicDataIoctl: forensic data type error %d\n", pForensicDataPayload->DataType));
         status = IOCTL_CALL_INVALID_CODE;
         return status;
  }

  if ( saGetForensicData(agRoot, agNULL, &ForensicData) != AGSA_RC_SUCCESS )
  {
    status = IOCTL_CALL_FAIL;
  }

  return status;
}

osGLOBAL bit32
tdsaSendSMPIoctl(
                tiRoot_t            *tiRoot,
                tiIOCTLPayload_t    *agIOCTLPayload,
                void                *agParam1,
                void                *agParam2,
                void                *agParam3
                )
{
	tdsaRoot_t		*tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
	tdsaContext_t	*tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
	agsaRoot_t		*agRoot = &(tdsaAllShared->agRootInt);
	void			*reqBuffer = agNULL;
	void			*respBuffer = agNULL;
	void			*osMemHandle = agNULL;
	bit32			status = IOCTL_CALL_SUCCESS;
//	bit32			Offset = 0;
//	bit32			RequestLength = 0;
	bit32			ostiMemoryStatus = 0;
	smp_pass_through_req_t *smp_pass_through_req;
	
	tiDeviceHandle_t *devHandle;
	agsaSMPFrame_t			  agSMPFrame;
	tdsaDeviceData_t          *oneDeviceData = agNULL;
	bit32 i;
	
	TI_DBG2(("tdsaSendSMPIoctl: start\n"));
	
 	smp_pass_through_req = (smp_pass_through_req_t*)agIOCTLPayload->FunctionSpecificArea;

	for(i=0;i<8;i++)
		TI_DBG2(("SAS Address[%d]:%x",i,smp_pass_through_req->exp_sas_addr[i]));
	TI_DBG2(("SAS Request Length:%d",smp_pass_through_req->smp_req_len));
	TI_DBG2(("SAS Response Length:%d",smp_pass_through_req->smp_resp_len));
	for(i=0;i<smp_pass_through_req->smp_req_len;i++)
		TI_DBG2(("SAS request + %d:%x",i,smp_pass_through_req->smp_req_resp[i]));

	devHandle = ostiGetDevHandleFromSasAddr(tiRoot, smp_pass_through_req->exp_sas_addr);
	if(devHandle == NULL)
	{
		status = IOCTL_CALL_FAIL;
		agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
		return status;
	}
	

	
	//agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;
	agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_RESPONDING;
	


	if((ostiMemoryStatus != tiSuccess) && (reqBuffer == agNULL  ))
			return IOCTL_CALL_FAIL;
		
   
    tdsaAllShared->tdFWControlEx.param3 = osMemHandle;
	

	agSMPFrame.outFrameBuf = smp_pass_through_req->smp_req_resp;
	agSMPFrame.expectedRespLen = smp_pass_through_req->smp_resp_len;
	agSMPFrame.inFrameLen = smp_pass_through_req->smp_resp_len - 4;

	if(!(smp_pass_through_req->smp_req_len - 8) && !tiIS_SPC(agRoot))
	{
		agSMPFrame.flag = 1;  // Direct request Indirect response
		agSMPFrame.outFrameLen = smp_pass_through_req->smp_req_len - 4; //Exclude header
	}
	else
	{
	
		agSMPFrame.flag = 3;  //Indirect request and Indirect response
		ostiMemoryStatus = ostiAllocMemory( tiRoot,
										  &osMemHandle,
										  (void **)&reqBuffer,
										  &(agSMPFrame.outFrameAddrUpper32),
										  &(agSMPFrame.outFrameAddrLower32),
										  8,
										  smp_pass_through_req->smp_req_len,
										  agFALSE);
		tdsaAllShared->tdFWControlEx.param3 = osMemHandle;
		if(tiIS_SPC(agRoot))
		{
		  agSMPFrame.outFrameLen = smp_pass_through_req->smp_req_len - 4; //Exclude crc
		  osti_memcpy((void *)reqBuffer, (void *)(smp_pass_through_req->smp_req_resp), smp_pass_through_req->smp_req_len);
		}
		else
		{
		  agSMPFrame.outFrameLen = smp_pass_through_req->smp_req_len - 8; //Exclude header and crc
		  osti_memcpy((void *)reqBuffer, (void *)(smp_pass_through_req->smp_req_resp + 4), smp_pass_through_req->smp_req_len - 4);
		}
	}

	ostiMemoryStatus = ostiAllocMemory( tiRoot,
										  &osMemHandle,
										  (void **)&respBuffer,
										  &(agSMPFrame.inFrameAddrUpper32),
										  &(agSMPFrame.inFrameAddrLower32),
										  8,
										  smp_pass_through_req->smp_resp_len + 4,
										  agFALSE);
	if((ostiMemoryStatus != tiSuccess) && (respBuffer == agNULL  ))
			return IOCTL_CALL_FAIL;
		

	osti_memset((void *)respBuffer, 0, smp_pass_through_req->smp_resp_len);
	
		// use FW control place in shared structure to keep the neccesary information
	tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
	tdsaAllShared->tdFWControlEx.virtAddr = respBuffer;
	tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)smp_pass_through_req->smp_req_resp + smp_pass_through_req->smp_req_len;
	tdsaAllShared->tdFWControlEx.len = smp_pass_through_req->smp_resp_len;
	tdsaAllShared->tdFWControlEx.param1 = agParam1;
	tdsaAllShared->tdFWControlEx.param2 = agParam2;
	tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
	tdsaAllShared->tdFWControlEx.inProgress = 1;
	status = IOCTL_CALL_PENDING;

	oneDeviceData = (tdsaDeviceData_t *)devHandle->tdData;
	if(saSendSMPIoctl(agRoot, oneDeviceData->agDevHandle, 0, &agSMPFrame, &ossaSMPIoctlCompleted) != AGSA_RC_SUCCESS)
	{
	  status = IOCTL_CALL_FAIL;
	  agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
	}
	return status;
}

osGLOBAL void ostiSendSMPIOCTLRsp(
                        tiRoot_t            *tiRoot,
                        bit32               status
                        )
{
    tdsaRoot_t           *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
    tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
    tiIOCTLPayload_t     *agIOCTLPayload;

    agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
    agIOCTLPayload->Status = (bit16)status;

    TI_DBG1(("ostiSendSMPIOCTLRsp: start, status = %d\n", status));

//	if(tdsaAllShared->tdFWControlEx.param1 != agNULL)
//	{
      osti_memcpy((void *)(tdsaAllShared->tdFWControlEx.usrAddr),
                  (void *)(tdsaAllShared->tdFWControlEx.virtAddr),
                  tdsaAllShared->tdFWControlEx.len);
//	}
	ostiFreeMemory(tiRoot,
                   tdsaAllShared->tdFWControlEx.buffer,
                   tdsaAllShared->tdFWControlEx.len);
	ostiFreeMemory(tiRoot,
                   tdsaAllShared->tdFWControlEx.param3,
                   tdsaAllShared->tdFWControlEx.len);
    //if(tdsaAllShared->tdFWControlEx.param1 != agNULL)
//	{
      ostiIOCTLComplete(tiRoot, 
                         tdsaAllShared->tdFWControlEx.param1,
                         tdsaAllShared->tdFWControlEx.param2,
                         NULL);
//    }
}




/*****************************************************************************
*
* tdsaSendBISTIoctl
*
* Purpose:  This routine is called to get Forensic Data.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   agIOCTLPayload: Pointer to the IOCTL payload.
*   agParam1:       Pointer to pass context handle for IOCTL DMA operation
*   agParam2:       Pointer to pass context handle for IOCTL DMA operation
*   agParam3:       Pointer to pass context handle for IOCTL DMA operation
*
* Return:
*
*   IOCTL_CALL_SUCCESS        The requested operation completed successfully.
*   IOCTL_CALL_FAIL           Fail to complete the IOCTL request.
*                             Detail error code is function specific and
*                             defined by the specific IOCTL function.
*   IOCTL_CALL_PENDING        This request is asynchronous and completed
*                             in some other context.
*   IOCTL_CALL_INVALID_CODE   This IOCTL function is not recognized.
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaSendBISTIoctl(
                 tiRoot_t            *tiRoot,
                 tiIOCTLPayload_t    *agIOCTLPayload,
                 void                *agParam1,
                 void                *agParam2,
                 void                *agParam3
                 )
{
  tdsaRoot_t      *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t   *tdsaAllShared   = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t      *agRoot          = &(tdsaAllShared->agRootInt);
  tdBistPayload_t *pBistPayload;
//  bit32            length = 0;
//  bit32            status = IOCTL_CALL_SUCCESS;
  bit32            status = IOCTL_CALL_FAIL;

  pBistPayload = (tdBistPayload_t*)agIOCTLPayload->FunctionSpecificArea;

  tdsaAllShared->tdFWControlEx.buffer = agNULL;
  tdsaAllShared->tdFWControlEx.virtAddr = agNULL;
  tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0];
  tdsaAllShared->tdFWControlEx.len = 0;
  tdsaAllShared->tdFWControlEx.param1 = agParam1;
  tdsaAllShared->tdFWControlEx.param2 = agParam2;
  tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
  tdsaAllShared->tdFWControlEx.inProgress = 0;

  TI_DBG1(("tdsaSendBISTIoctl: Type %d Length %d Data %p\n",
      pBistPayload->testType,
      pBistPayload->testLength,
      pBistPayload->testData ));


  // pBistPayload->testtype = AGSA_BIST_TEST;

  if( pBistPayload->testType == AGSA_BIST_TEST)
  {
    if( pBistPayload->testLength != sizeof(agsaEncryptSelfTestBitMap_t))
    {
      return status;
    }
  }
  else if( pBistPayload->testType == AGSA_SHA_TEST)
  {
    if( pBistPayload->testLength != sizeof(agsaEncryptSHATestDescriptor_t) )
    {
      return status;
    }
  }
  else if( pBistPayload->testType == AGSA_HMAC_TEST )
  {
    if( pBistPayload->testLength != sizeof(agsaEncryptHMACTestDescriptor_t))
    {
      return status;
    }
  }

/*
GLOBAL bit32 saEncryptSelftestExecute(
                        agsaRoot_t    *agRoot,
                        agsaContext_t *agContext,
                        bit32         queueNum,
                        bit32         type,
                        bit32         length,
                        void          *TestDescriptor);

*/
  if ( saEncryptSelftestExecute(agRoot,
        agNULL,
        0,
        pBistPayload->testType,
        pBistPayload->testLength,
        pBistPayload->testData  ) != AGSA_RC_SUCCESS )
  {
    status = IOCTL_CALL_FAIL;
  }

  return status;
}


osGLOBAL bit32
tdsaSendTMFIoctl( tiRoot_t	     	*tiRoot,
		  tiIOCTLPayload_t	*agIOCTLPayload,
		  void                  *agParam1,
		  void			*agParam2,
		  unsigned long		resetType
		)
{
	bit32		status;
	tmf_pass_through_req_t  *tmf_req = (tmf_pass_through_req_t*)agIOCTLPayload->FunctionSpecificArea;
#if !(defined(__FreeBSD__))
	status = ostiSendResetDeviceIoctl(tiRoot, agParam2, tmf_req->pathId, tmf_req->targetId, tmf_req->lun, resetType);
#endif
	TI_DBG3(("Status returned from ostiSendResetDeviceIoctl is %d\n",status));
	if(status !=  IOCTL_CALL_SUCCESS)
	{
		agIOCTLPayload->Status = status;
		return status;
	}
	status = IOCTL_CALL_SUCCESS;
	return status;
}


#ifdef VPD_TESTING
/* temporary to test saSetVPDCommand() and saGetVPDCommand */
osGLOBAL bit32
tdsaVPDSet(
                tiRoot_t            *tiRoot
                )
{
  tdsaRoot_t    *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t    *agRoot = &(tdsaAllShared->agRootInt);
  bit32         status = IOCTL_CALL_SUCCESS;
  agsaVPD_t     VPDInfo;
  bit32         ret = AGSA_RC_SUCCESS;

  bit32                 bufAddrUpper = 0;
  bit32                 bufAddrLower = 0;
  tdVPDControl_t        *VPDControl;

  void                  *osMemHandle = agNULL;
  void                  *buffer;
  bit32                 timeCount=0;
  bit8                  ioctlErr=0;
  bit8                  VPDPayload[32];
  bit8                  i;
  TI_DBG2(("tdsaVPDSet: start\n"));

  for(i=0;i<sizeof(VPDPayload);i++)
  {
    VPDPayload[i] = i;
  }
  if(ostiAllocMemory( tiRoot,
                        &osMemHandle,
                        (void **)&buffer,
                        &bufAddrUpper,
                        &bufAddrLower,
                        8,
                        sizeof(VPDPayload),
                        agFALSE))
  {
    return tiError;
  }
  osti_memcpy((void *)buffer,
               VPDPayload,
               sizeof(VPDPayload));


  osti_memset(&VPDInfo, 0, sizeof(agsaVPD_t));
#ifdef NOT_YET /* direct mode worked */
  /* For now, only direct mode */
  VPDInfo.indirectMode = 0; /* direct mode */
  VPDInfo.VPDDevice = 1; /* SEEPROM-1 */
  VPDInfo.directLen  = (bit8)sizeof(VPDPayload);
  VPDInfo.VPDOffset = 0;
  VPDInfo.directData = buffer;
  VPDInfo.indirectAddrUpper32 = bufAddrUpper;
  VPDInfo.indirectAddrLower32 = bufAddrLower;
  VPDInfo.indirectLen = sizeof(VPDPayload);
#endif

  /* indirect mode */
  VPDInfo.indirectMode = 1; /* indirect mode */
  VPDInfo.VPDDevice = 1; /* SEEPROM-1 */
  VPDInfo.directLen  = 0;
  VPDInfo.VPDOffset = 0;
  VPDInfo.directData = agNULL;
  VPDInfo.indirectAddrUpper32 = bufAddrUpper;
  VPDInfo.indirectAddrLower32 = bufAddrLower;
  VPDInfo.indirectLen = sizeof(VPDPayload);

  tdsaAllShared->tdFWControlEx.buffer = osMemHandle;
  tdsaAllShared->tdFWControlEx.param1 = agParam1;
  tdsaAllShared->tdFWControlEx.param2 = agParam2;

  /* for testing only */
  tdsaAllShared->addrUpper = bufAddrUpper;
  tdsaAllShared->addrLower = bufAddrLower;

  ret = saSetVPDCommand(agRoot, agNULL, 0, &VPDInfo);

  if (ret == AGSA_RC_SUCCESS)
  {
    status = tiSuccess;
  }
  else
  {
    status = tiError;
  }

    ostiFreeMemory(tiRoot, osMemHandle, sizeof(VPDPayload));
  return status;
}

/* temporary to test saSetVPDCommand() and saGetVPDCommand */
osGLOBAL bit32
tdsaVPDGet(tiRoot_t            *tiRoot)
{
  tdsaRoot_t    *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t    *agRoot = &(tdsaAllShared->agRootInt);
  bit32         status = IOCTL_CALL_SUCCESS;
  agsaVPD_t     VPDInfo;
  bit32         ret = AGSA_RC_SUCCESS;


  TI_DBG2(("tdsaVPDGet: start\n"));

  osti_memset(&VPDInfo, 0, sizeof(agsaVPD_t));

  /* direct mode worked */
  VPDInfo.indirectMode = 0; /* direct mode */
  VPDInfo.VPDDevice = 1; /* SEEPROM-1*/
  VPDInfo.directLen  = 32;
  VPDInfo.VPDOffset = 0;
  VPDInfo.directData = agNULL;
  VPDInfo.indirectAddrUpper32 = 0;
  VPDInfo.indirectAddrLower32 = 0;
  VPDInfo.indirectLen = 0;


#ifdef NOT_YET /* worked; can't read VPD in ossaGetVPDResponseCB() because of indirect */
  VPDInfo.indirectMode = 1; /* direct mode */
  VPDInfo.VPDDevice = 1; /* SEEPROM-1*/
  VPDInfo.directLen  = 0;
  VPDInfo.VPDOffset = 0;
  VPDInfo.directData = agNULL;
  VPDInfo.indirectAddrUpper32 = tdsaAllShared->addrUpper;
  VPDInfo.indirectAddrLower32 = tdsaAllShared->addrLower;
  VPDInfo.indirectLen = 32;
#endif
  ret = saGetVPDCommand(agRoot, agNULL, 0, &VPDInfo);

  if (ret == AGSA_RC_SUCCESS)
  {
    status = tiSuccess;
  }
  else
  {
    status = tiError;
  }
  return status;
}
#endif
/*****************************************************************************
*
* tdsaGetNumOfLUNIOCTL
*
* Purpose:  This routine is called to send Report LUN SSP command request.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   tiIOCTLPayload_t:        Status of the Controller Reset.
*   agParam1:        Void pointer to device extension
*   agParam2:        Void pointer to SRB
*   agParam3:        NULL
*
*   Return: status
*
*
*****************************************************************************/
osGLOBAL bit32
tdsaGetNumOfLUNIOCTL(
               tiRoot_t            *tiRoot,
               tiIOCTLPayload_t    *agIOCTLPayload,
               void                *agParam1,
               void                *agParam2,
               void                *agParam3
               )
{  
  tdsaRoot_t	              *tdsaRoot			= (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t               *tdsaAllShared 	= (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  agsaRoot_t	              *agRoot 			= &(tdsaAllShared->agRootInt);
  tdDeviceLUNInfoIOCTL_t	  *pDeviceLUNInfo	= agNULL;
  tiDeviceHandle_t            *devHandle 		= agNULL;
  void				          *tiRequestBody 	= agNULL;
  tiIORequest_t 	          *tiIORequest 		= agNULL;
  bit32			              status 			= IOCTL_CALL_SUCCESS;	
  
  TI_DBG2(("tdsaGetNumOfLUNIOCTL: Start\n"));  
  do
  {
    pDeviceLUNInfo = (tdDeviceLUNInfoIOCTL_t*)agIOCTLPayload->FunctionSpecificArea;
  
    if (agIOCTLPayload->Length < sizeof(tdDeviceLUNInfoIOCTL_t))
    {
  	  status = IOCTL_CALL_FAIL;
  	  break;
    }
    if(!pDeviceLUNInfo->tiDeviceHandle)
    {
      status = IOCTL_CALL_FAIL;
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
      break;
    }
	devHandle = (tiDeviceHandle_t*)pDeviceLUNInfo->tiDeviceHandle;
	agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK;

	status = ostiNumOfLUNIOCTLreq(tiRoot,agParam1,agParam2,&tiRequestBody,&tiIORequest);

	
    if(status != AGSA_RC_SUCCESS) 	
    {
      agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
	  break;
    }
    status = tiNumOfLunIOCTLreq(tiRoot,tiIORequest,devHandle,tiRequestBody,agIOCTLPayload,agParam1,agParam2);
    
    if(status != AGSA_RC_SUCCESS)	
    {
         agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR;
	  break;
    }
//	ostiIOCTLWaitForSignal (tiRoot, agParam1, agParam2, agParam3);

  }while(0);
  TI_DBG2(("tdsaGetNumOfLUNIOCTL: End\n"));
  return status;
}


/*****************************************************************************
*
* ostiNumOfLUNIOCTLRsp
*
* Purpose:  This routine is called when a Report LUN SSP command response id recieved.
*
* Parameters:
*   tiRoot:         Pointer to driver instance
*   bit32               status
*
* Return: none
*
*
*****************************************************************************/
osGLOBAL void ostiNumOfLUNIOCTLRsp(
                        tiRoot_t            *tiRoot,
                        bit32               status
                        )
{
  tdsaRoot_t                  *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  tiIOCTLPayload_t            *agIOCTLPayload;
  tdDeviceLUNInfoIOCTL_t	  *pDeviceLUNInfo = NULL;
  bit32                       count = 0;
  bit32                       numOfLUN =0;
  
  TI_DBG1(("ostiNumOfLUNIOCTLRsp: start, status = %d\n", status));

  if(tdsaAllShared->tdFWControlEx.inProgress == 1)
  {
    agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload);
	if ((agIOCTLPayload) && (PMC_IOCTL_SIGNATURE == agIOCTLPayload->Signature)&& 
					   (IOCTL_MJ_GET_DEVICE_LUN == agIOCTLPayload->MajorFunction))
	{
      agIOCTLPayload->Status = (bit16)status;
      pDeviceLUNInfo = (tdDeviceLUNInfoIOCTL_t*)agIOCTLPayload->FunctionSpecificArea;
      numOfLUN = ((tdsaAllShared->tdFWControlEx.virtAddr[0] << 24)|(tdsaAllShared->tdFWControlEx.virtAddr[1] << 16)|\
                 (tdsaAllShared->tdFWControlEx.virtAddr[2] << 8)|(tdsaAllShared->tdFWControlEx.virtAddr[3])); 
      numOfLUN = numOfLUN/8;
      pDeviceLUNInfo->numOfLun = numOfLUN;
//	  ostiFreeMemory(tiRoot,
//                     tdsaAllShared->tdFWControlEx.virtAddr,
//                     tdsaAllShared->tdFWControlEx.len);   
  //    if(tdsaAllShared->tdFWControlEx.param1 != agNULL)
  //    {
        ostiIOCTLSetSignal(tiRoot, 
                           tdsaAllShared->tdFWControlEx.param1,
                           tdsaAllShared->tdFWControlEx.param2,
                           NULL);
  	    tdsaAllShared->tdFWControlEx.payload = NULL; 	    
  //    }
	  
	  tdsaAllShared->tdFWControlEx.inProgress = 0;
	}
  }
  TI_DBG1(("ostiNumOfLUNIOCTLRsp: End\n"));
}

